Backup Blog

I have decided to backup this blog. First time. So following instructions from wordpress.

  • 1- Backup Database:
https://your_domain_or_IP/phpmyadmin
https://wordpress.org/support/article/backing-up-your-database/
  • 2- Backup webserver files
root@vps:/var/www# ls
html wordpress
root@vps:/var/www# cd ..
root@vps:/var# tar zcvf web-backup.tgz www
  • 3- Transfer the tgz and the sql file to a folder in my laptop that is backed-up to external hard drive.
/blog-backup$ tree
.
├── apache-files
│   └── web-backup-20200707.tgz
└── mysql
    └── blog-backup-20200707.sql

Netbox

Another thing I wanted to play with is Netbox and found a good article to follow. So credits to the authors.

Using my current ceos lab from https://github.com/thomarite/ceos-testing

I followed Rick’s article to install netbox-docker and his own repo with the nornir examples using netbox. In this case nornir is going to use netbox as inventory. Normally I use local files. I created a python venv for 3.7.3

mkdir netbox-example; cd netbox-example
pyenv local 3.7.3
python -m virtualenv venv
source venv/bin/activate
git clone https://github.com/netbox-community/netbox-docker.git
cd netbox-docker
vim docker-compose.yml  --> so it always expose 8080
      nginx:
      ...
        ports:
          - 8080:8080
docker-compose pull
docker-compose up

When installing the requirements for “nornir-napalm-netbox-demo” I had to modify the version of some packages. So I removed the required version and I left pip to install the latest. I didnt use the makefile.

git clone https://github.com/rickdonato/nornir-napalm-netbox-demo
cd nornir-napalm-netbox-demo
python -m pip install -r requirements.txt

I struggled quite a bit with the management IP in netbox and the meaning of “platform”

  • Create Manufacturers under Device Types: I created “Arista”
  • Create Device Types under Device Types: I created “ceos”
  • Create Platforms under Devices: This is VERY important as it has to be a supported NAPALM platform!!! So for Arista, I need “eos”.
  • Create Device Roles under Devices. I created “pe”
  • Create Devices under Devices.
  • Within each device: add a management interface. Here, I got confused as I was adding the interface in the inventory section. The inventory section is info to/from the device using NAPALM. So you need to go to the bottom of the page, add the interface
  • and then add an IP to that interface and mark it as primary.

Keep in mind that initially, I was using “0.0.0.0” for each device as that’s the IP I have be using for all my scripts lately.

Keep in mind (II) that we are using docker twice (from different commands…) one to get netbox and the other via docker(-topo) to get the Arista ceos containers…. and we have iptables rules under the hood created by both…

But, let’s go step by step. Now we need to confirm that our nornir scrip can connect to netbox. So follow “Nornir-to-Netbox Configuration” section. This is my file. I updated the nb_url and nb_token. Notice the usage of “transform_function“.

---
core:
num_workers: 20
inventory:
plugin: nornir.plugins.inventory.netbox.NBInventory
options:
nb_url: 'http://0.0.0.0:8080'
nb_token: '<NETBOX_API_TOKEN>'
ssl_verify: False
transform_function: "helpers.adapt_user_password"

You need to update “scripts/secrets.py” with the devices you have in your inventory and the user/pass:

creds = {
"r1": {"username": "user", "password": "pas123"},
"r2": {"username": "user", "password": "pas123"},
"r3": {"username": "user", "password": "pas123"},
}

So now we can test if nornir can connect to netbox:

/netbox-example/nornir-napalm-netbox-demo master$ python scripts/helpers.py --inventory
{'defaults': {'connection_options': {},
'data': {},
'hostname': None,
'password': None,
'platform': None,
'port': None,
'username': None},
'groups': {},
'hosts': {'r1': {'connection_options': {},
'data': {'asset_tag': 'r1',
'model': 'ceos',
'role': 'pe',
'serial': 'r1',
'site': 'lab1',
'vendor': 'Arista'},
'groups': [],
'hostname': '192.168.16.2',
'password': 'pas123',
'platform': 'eos',
'port': None,
'username': 'user'},
'r2': {'connection_options': {},
'data': {'asset_tag': 'r2',
'model': 'ceos',
'role': 'pe',
'serial': 'r2',
'site': 'lab1',
'vendor': 'Arista'},
'groups': [],
'hostname': '192.168.16.3',
'password': 'pas123',
'platform': 'eos',
'port': None,
'username': 'user'},
'r3': {'connection_options': {},
'data': {'asset_tag': 'r3',
'model': 'ceos',
'role': 'pe',
'serial': 'r3',
'site': 'lab1',
'vendor': 'Arista'},
'groups': [],
'hostname': '192.168.16.4',
'password': 'pas123',
'platform': 'eos',
'port': None,
'username': 'user'}}}

All good. Let’s see if we can get backups from the devices.

netbox-example/nornir-napalm-netbox-demo master$ python scripts/backup_configs.py
Backup Device configurations**
r1 ** changed : True *
vvvv Backup Device configurations ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- napalm_get ** changed : False --------------------------------------------- INFO
---- write_file ** changed : True ---------------------------------------------- INFO
^^^^ END Backup Device configurations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
r2 ** changed : True *
vvvv Backup Device configurations ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- napalm_get ** changed : False --------------------------------------------- INFO
---- write_file ** changed : True ---------------------------------------------- INFO
^^^^ END Backup Device configurations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
r3 ** changed : True *
vvvv Backup Device configurations ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- napalm_get ** changed : False --------------------------------------------- INFO
---- write_file ** changed : True ---------------------------------------------- INFO
^^^^ END Backup Device configurations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(venv) /netbox-example/nornir-napalm-netbox-demo master$

Great all good.

Now, let’s see netbox using NAPALM. If you click on “Status” for any device, netbox will use NAPALM to get the facts from the device. If netbox is not configured properly with NAPALM, it will fail. This is a working scenario:

The tabs “LLDP neighbors” and “Configuration” relay too in NAPALM.

So for configuring netbox with napalm you need to tell netbox the user/pass that NAPALM needs:

netbox-example$ vim netbox-docker/env/netbox.env
...
NAPALM_USERNAME=user
NAPALM_PASSWORD=pas123
NAPALM_TIMEOUT=10
...

Very likely you will have to restart netbox:

/netbox-docker release$ docker-compose down
/netbox-docker release$ docker-compose up

As mentioned before, I had an issue when I was using “0.0.0.0” as IP. By default (as It seems I can’t think) I was using the exposed IP/port from docker-topo to reach the ceos switches. I haven’t had an issue until using netbox.

I am using docker for netbox and docker(-topo) for my arista cEOS switches. So the connectivity between netbox and ceos is via the IPs/interfaces/bridges created by docker. And remember… you have iptables under the hood. My first mistake was telling netbox to use 0.0.0.0 as it is the one I am using to testing from my scripts when connecting to ceos. Netbox needs to point to the IP assigned by docker :facepalm: 192.16.16.x in my case. Second one, the port, same thing docker exposes the port 443 as 900x for external connections and I use 900x in my scripts. From netbox point of view, it is still 443 :facepalm: And finally, I am calling docker twice for building my lab, one for netbox-docker and the other for ceos. You need to keep an eye on iptables changes when restarting netbox via docker-compose because you can be in the situation that netbox traffic is dropped in DOCKER-ISOLATION-STAGE-1 :facepalm: (need to try to write a docker-compose to build everything in one go)

So when I was having errors from netbox that it was being rejected when connecting to ceos devices via NAPALM, I couldnt understand it. My scripts were fine using those details (0.0.0.0:900x)

I ran tcpdump on one ceos on the “ethernet0” interface and NOTHING was hitting the interface from netbox on port 900x but my scripts could…..

Somehow netbox wasnt able to reach ceos r1??? In my head, netbox and ceos devices were all in 0.0.0.0….. so no routing, no firewalls, they are connected in the same network 0.0.0.0…..

At the end I waked up and realised that the docker devices are using the IPs provided by docker so it is following normal routing… and firewalling by iptables. The same for ceos devices, they have IPs (different from 0.0.0.0)

So I updated netbox with the correct management IPs for r1, r2 and r3 ceos.

When I filtered by the real netbox IP in r1 tcpdump ethernet0, I was seeing traffic on 900x!!! Good. Then I realised that it has to be 443. So I removed my hack to update the port to 900x.

For a different reason I had to restart docker-topo (for ceos) and then docker netbox. And now, I coudnt see any traffic from netbox in r1….. I “didn’t” change anything. So the routing didnt change, there was something else “cutting” the connection: iptables

docker uses iptables very heavily. I realised that after restart docker-netbox, iptables changed…

before restart:

# iptables -t filter -S DOCKER-ISOLATION-STAGE-1
Warning: iptables-legacy tables present, use iptables-legacy to see them
-N DOCKER-ISOLATION-STAGE-1
-A DOCKER-ISOLATION-STAGE-1 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i br-94a8183a4fb1 ! -o br-94a8183a4fb1 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-0d4ec9aba9bd ! -o br-0d4ec9aba9bd -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-609619313dc8 ! -o br-609619313dc8 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-61d32350cb58 ! -o br-61d32350cb58 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-384488acbc99 ! -o br-384488acbc99 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN

after restart:

# iptables -t filter -S DOCKER-ISOLATION-STAGE-1
Warning: iptables-legacy tables present, use iptables-legacy to see them
-N DOCKER-ISOLATION-STAGE-1
-A DOCKER-ISOLATION-STAGE-1 -i br-381cdff63d2f ! -o br-381cdff63d2f -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i br-94a8183a4fb1 ! -o br-94a8183a4fb1 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-0d4ec9aba9bd ! -o br-0d4ec9aba9bd -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-609619313dc8 ! -o br-609619313dc8 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-61d32350cb58 ! -o br-61d32350cb58 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN

With the restart, docker created a new bridge interface for netbox (old: br-384488acbc99, new: br-381cdff63d2f) and it wasnt hitting anymore the “DOCKER-ISOLATION-STAGE-1 -j ACCEPT”

So I had to make an iptables change:

# iptables -t filter -D DOCKER-ISOLATION-STAGE-1 -j ACCEPT
# iptables -t filter -I DOCKER-ISOLATION-STAGE-1 -j ACCEPT
# iptables -t filter -S DOCKER-ISOLATION-STAGE-1
Warning: iptables-legacy tables present, use iptables-legacy to see them
-N DOCKER-ISOLATION-STAGE-1
-A DOCKER-ISOLATION-STAGE-1 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i br-381cdff63d2f ! -o br-381cdff63d2f -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-94a8183a4fb1 ! -o br-94a8183a4fb1 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-0d4ec9aba9bd ! -o br-0d4ec9aba9bd -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-609619313dc8 ! -o br-609619313dc8 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-61d32350cb58 ! -o br-61d32350cb58 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
#

And finally, netbox could use napalm to contact the ceos devices…. Calling docker twice is not a great idea….

BTW, this is my docker ps with netbox and ceos devices:

(venv) /netbox-example$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c23be76ffd54 nginx:1.17-alpine "nginx -c /etc/netbo…" 4 hours ago Up 4 hours 80/tcp, 0.0.0.0:8080->8080/tcp netbox-docker_nginx_1
5a0b89f18578 netboxcommunity/netbox:latest "/opt/netbox/docker-…" 4 hours ago Up 4 hours netbox-docker_netbox_1
528948de329b netboxcommunity/netbox:latest "python3 /opt/netbox…" 4 hours ago Up 4 hours netbox-docker_netbox-worker_1
29529302ba1c redis:5-alpine "docker-entrypoint.s…" 4 hours ago Up 4 hours 6379/tcp netbox-docker_redis_1
5e975ec2aa70 redis:5-alpine "docker-entrypoint.s…" 4 hours ago Up 4 hours 6379/tcp netbox-docker_redis-cache_1
6158672a4ae6 postgres:11-alpine "docker-entrypoint.s…" 4 hours ago Up 4 hours 5432/tcp netbox-docker_postgres_1
34841aa098d4 ceos-lab:4.23.3M "/sbin/init systemd.…" 5 hours ago Up 5 hours 0.0.0.0:2002->22/tcp, 0.0.0.0:9002->443/tcp 3node_r03
4ca92c6a3b09 ceos-lab:4.23.3M "/sbin/init systemd.…" 5 hours ago Up 5 hours 0.0.0.0:2001->22/tcp, 0.0.0.0:9001->443/tcp 3node_r02
67e8b7ab84e0 ceos-lab:4.23.3M "/sbin/init systemd.…" 5 hours ago Up 5 hours 0.0.0.0:2000->22/tcp, 0.0.0.0:9000->443/tcp 3node_r01

I was painful but I learned a couple of things about netbox, nornir and docker/iptables!!!

Dynamic DNS

I am using GCP for EVE-NG but I dont have permanent public IPs for the VMs as it has a cost and they are not running all the time. I am not really bother about that but talking with a friend a couple of weeks ago he wanted to have a public IP to his home lab using a commercial broadband that obviously provides dynamic IPs. So I searched a bit and found different solutions and found this:

https://www.duckdns.org

For my needs it is enough. It is free up to 5 domains. And you dont have to install any software in your systems. Just a cron job calling a basic script with one line.

The thing I don’t like. If you don’t pay with money… you pay with your data. You have to use an account from Twitter, Google, Reddit or Github. Fortunately I have an account from one of those services that I dont use so it has minimum data.

Choco Cookies

It is something I have never tried to bake. I consider it a very American/British thing. I have tried good ones in UK in Ben’s Cookies and it seems there is a great version in USA in Levain Bakery.

So searching for recipes, I chose this one:

Ingredients (adapted to what I have):

Plain flour 200g
Self-Raising flour 100g
100% cocoa powder 50g
1 teaspoon of corn flour
1 teaspoon of baking soda
1 teaspoon of baking powder
Half a teaspoon of salt

Cold butter 200g
Brown sugar 130g
White sugar 70g

2 free range eggs - beaten room temperature 

300g 80% dark chocolate in pieces
20g of mixed nuts crashed

Process:

  • Sieve flour, cocoa powder, corn, baking soda/powder, and salt.
  • Cut the cold butter into a small cubes.
  • Chop chocolate tablets into small pieces.
  • In a big enough bowl, cream the butter and sugar. I do it by hand.
  • Add eggs in 3 separate steps, and keep mixing.
  • Add the dry ingredients (flour mix), and mix lightly until you still see unmixed flour.
  • Add chocolate pieces and nuts. Mix lightly.
  • Cover and move the dough to the fridge for 2-3 hours.
  • Weight 170gr of dough per cookie. Make a ball and place it on a tray.
  • Move the try to the fridge for 30 minutes in the fridge.
  • Pre heat the oven to 200℃ and bake it at 180℃ for 10 minutes.
  • Let them rest for 15 minutes or more until the surface is a bit hard. If not they will break down in your hand.

Veredict

Obviously, they dont look like the ones in the video or the other sites but they were good.

Difficult to believe, but they dont taste super sweet. I used 100% cocoa powder and 85% dark chocolate. Still one cookie has the amount of chocolate and sugar that I take in one week 😛

Reminder

You can put the rest of cookies in the freezer! And enjoy fresh baked cookies any day!!! (I had three left over)

Mistakes

  • They where in the oven for 13 minutes or more… so they flat out more than I wished.
  • They are very big cookies so make sure they have plenty of room. I only put four and one moved when I put the tray in the oven.

Another time, I will try the walnut one.

The Great Suspender

No, it is not me when I was a kid. It is a GC extension. I have a very bad habit of opening many tabs in my browser with the excuse, I will take a look later. That takes a big toll in CPU/Memory. With this extension, my laptop is running very smoothly even when I have three cEOS docker boxes running in the background. The fan runs less often. I have been using it for over a week and I am very happy with it. Need to find something for Firefox.

Github + ssh-key

There are many links for this in the Internet so I am not going to discover the fire but I struggled a bit so….

The official links from github were ok and other people did a very good job too documenting the process.

https://docs.github.com/en/github/authenticating-to-github/testing-your-ssh-connection

https://docs.github.com/en/github/authenticating-to-github/error-permission-denied-publickey

https://jdblischak.github.io/2014-09-18-chicago/novice/git/05-sshkeys.html

I had already a key that I wanted to use. So adding it to the repo was ok.

Testing it was my challenge. I was missing two things. My key wasn’t following the standard file name so it wasn’t used by my ssh-agent and then, i wasn’t using the “git” user when testing…. I was using my github username.

So add the key and check it is there.

$ ssh-add ~/.ssh/id_ed25519-gh
$ ssh-add -l -E md5
256 MD5:xx:xx:xx:xx:xx:67:xx:6a:73:xx:8a:xx:7f:78:xx:xx user@gh (ED25519)

Check you can ssh to github.

$ ssh -T git@github.com
Hi xxxx! You've successfully authenticated, but GitHub does not provide shell access.
$

Ok, all good now. But this is not a new repo, how I move from the “old” user/pass to the “new” ssh-key process?

You can clone the repo again using ssh:

Or you can change the git config locally in the “url” bit.

/ceos-testing/.git master$ cat config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
#url = https://github.com/thomarite/ceos-testing.git
url = git@github.com:thomarite/ceos-testing.git
fetch = +refs/heads/:refs/remotes/origin/
[branch "master"]
remote = origin
merge = refs/heads/master
$

After that you can “git push” using your ssh-key.

2023-01

Looks like I dont learn the lesson….

1- Create Key

$ ssh-keygen -t ed25519 -C "your@email.com"
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/USERNAME/.ssh/id_ed25519): /home/USERNAME/.ssh/id_ed25519.github

2- Upload key to Github

3- Start agent and add key

$ ssh-agent -s
SSH_AUTH_SOCK=/tmp/ssh-XXXXXXjMtZn7/agent.250293; export SSH_AUTH_SOCK;
SSH_AGENT_PID=250294; export SSH_AGENT_PID;
echo Agent pid 250294;
$ ssh-add ~/.ssh/id_ed25519.github
Identity added: /home/USERNAME/.ssh/id_ed25519.github (your@email.com)
$ 

4- Authenticate to git

$ ssh -T git@github.com
Hi USERNAME! You've successfully authenticated, but GitHub does not provide shell access.
$ 

5- Push to git. Be sure your repo is not using https! Change it as showed here.

$ git remote get-url origin
https://github.com/SOMEBODY/scripts.git
$ git remote set-url origin git@github.com:SOMEBODY/scripts.git
$ 
$ git remote get-url origin
git@github.com:SOMEBODY/scripts.git
$ 
$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 2.07 KiB | 2.07 MiB/s, done.
Total 4 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.com:SOMEBODY/scripts.git
   6a4cb1a..07a4a83  main -> main
$ 

Which SSH keyfile was used to authenticate a login?

I have realised that I had two keys in my VPS and I wasn’t sure which one it was used when I was ssh-ing so I had to search a bit to find out.

These two links cover the process:

https://unix.stackexchange.com/questions/15575/can-i-find-out-which-ssh-key-was-used-to-access-an-account

https://unix.stackexchange.com/questions/147295/how-can-i-determine-which-ssh-keyfile-was-used-to-authenticate-a-login

1- You need to increase the logging of your sshd (destination – server)

server# vim /etc/ssh/sshd_config
LogLevel VERBOSE
server# service sshd restart
server# tail -f /var/log/auth.log

2- From client, just ssh as usual to the server and check auth.log as per above

Jul 3 14:17:55 server sshd[8600]: Connection from IPV6 port 57628 on IPV6::453 port 64022
Jul 3 14:17:55 server sshd[8600]: Postponed publickey for client from IPv6 port 57628 ssh2 [preauth]
Jul 3 14:17:55 server sshd[8600]: Accepted publickey for client from IPv6 port 57628 ssh2: ED25519 SHA256:BtOAX9eVpFJJgJ5HzjKU8E973m+MX+3gDxsm7eT/iEQ
Jul 3 14:17:55 server sshd[8600]: pam_unix(sshd:session): session opened for user client by (uid=0)
Jul 3 14:17:55 server sshd[8600]: User child is on pid 8606
Jul 3 14:17:55 server sshd[8606]: Starting session: shell on pts/7 for client from IPv6 port 57628 id 0

3- So we have the fingertip of the key used by client. Now we need to get the fingertips of our clients keys to find the match:

client $ ssh-keygen -l -f ~/.ssh/id_ed25519.pub
256 SHA256:BtOAX9eVpFJJgJ5HzjKU8E973m+MX+3gDxsm7eT/iEQ client@local (ED25519)

4- So the we can see that I am using my id_ed25519.pub key to connect to the server

Nornir

Nornir is a python framework mainly for network automation. Instead of using another tool like Ansible (that you need to learn), you can do the same just using pure python all the way. Ansible doesnt scale well and can be very slow, with nornir you have threading from day zero, so if you have to run tasks in 100 devices, you will feel and see the difference.

I learnt about nornir via Kirk Byers’ course. Unfortunately I didnt have the chance/time to use it in my former day job so now I have had time to review things and do a small project.

From https://github.com/thomarite/ceos-testing in the nornir section you can find the whole environment. I tested on the 3-node topology.

It is nothing special. The script builds the config for BGP or ISIS using jinj2 and yaml files. I have the feeling that my jinja2 is a bit difficult to follow. Then using napalm connects to the devices to push or check the config.

Just one issue, as it seems due to the nature of cEOS relaying on docker and my filesystem, if you decide to push the config (dry_run=False == commit=True) the task will fail (while trying to write startup config) but it is actually executed.

(testdir2) /testdir2/ceos-testing/nornir master$ python buid-config.py -b isis -c
hostname: r1
task: deploy_config for isis
failed: True
logs: Traceback (most recent call last):
...
File ".../testdir2/lib/python3.7/site-packages/pyeapi/eapilib.py", line 469, in send
raise CommandError(code, msg, command_error=err, output=out)
pyeapi.eapilib.CommandError: Error [1000]: CLI command 5 of 5 'write memory' failed: could not run command [Error copying system:/running-config to flash:/startup-config (Operation not permitted)]
changed: False
diff:

hostname: r2
task: deploy_config for isis
failed: False
logs: None
changed: False
diff:

hostname: r3
task: deploy_config for isis
failed: False
logs: None
changed: False
diff:

This shouldn’t happen on vEOS or the real hardware (if you have the correct aaa config of course)

Route Reflectors – Notes

Reflect:
client -> clients and non-clients
non-client -> clients
No Reflect:
non-client -> no-client (normal ibgp)

always advertises to eBGP peers (normal ebgp)
eBGP learned prefixes, advertised to client and non-clients (normal ebgp)

Full Mesh iBGP:

  • between RRs
  • RRs and non-clients
  • clients just need iBGP to RRs.

Reflects ONLY the best route

RRs dont modify on reflected routes: NEXT_HOP, AS_PATH, LP and MED.

Prevent routing information loops: ORIGINATOR_ID and CLUSTER_LIST

Clustering:

  • ORIGINATOR_ID: The first RR creates the Originator_ID and sets it to the BGP router ID of the router that originates the route. So when a client receives a route with its own Originator ID, it is dropped.
  • CLUSTER_LIST: if the local CLUSTER_ID is found in the list, the route is discarded.
    *This is done ONLY in RRs.
    This is ONLY created or updated on a RR during Reflection.
Hierarchical Route Reflection:
2 levels:
- level1 RRs are clients of level2 RR -> level1 RR dont need full mesh between them
- level2 RRs are full mesh between them.

Consider:
size of top-level mesh
number of alternative paths

Hierarchical Route Reflection:
2 levels:

– level1 RRs are clients of level2 RR -> level1 RR dont need full mesh between them
– level2 RRs are full mesh between them.

Consider:

  • size of top-level mesh
  • number of alternative paths

RR Design Priciples:

  • keep logical and physical topologies congruent to increase redundancy and path optimization and prevent loops
    — follow physical topology
    — change physical topology
    — modify logical topology
    — follow physical topology
    — session between RR and non-client shouldnt traverse a client
    — session between RR and client shouldnt traverse a non-client
  • use comparable metrics in route selection to avoid convergence oscillations
    (ie MED – only used between prefixes from same neighbor AS – not used for different AS)
    — full ibgp mess –> no
    — always-compare-med –> no
    — deterministic-med -> ok
    — med=0 (via RM in) -> ok
    — bgp communities ->
  • set proper intra and inter cluster IGP metrics to avoid convergence oscillations
    — multicluster RR architecture: intracluster metrics lower than intercluster.
  • modify next-hop with care. Do so only to bring the RRs into forwarding path.
  • use peer groups with RR to reduce convergence time.