All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit ea9bd892 authored by Simon Redman's avatar Simon Redman

Add helper for generating and setting routable ipv6 addresses

parent 3265d84a
#!/usr/bin/env python3
# Copyright (C) 2018 Simon Redman <>
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import ssh_helper
import argparse
import getpass
import ipaddress
from netdiff import NetJsonParser
import re
INTERFACE_ID_COMMAND = "ip -6 address list"
def parse_local_interface_addresses(netgraph):
For each ssh session, query the remote for its interfaces, then parse that for its IPv6 interface ID on each interface
:param netgraph: topology map, annotated with logged-in ssh sessions
:return: mapping of hosts to map of interfaces to that interface's IPv6 interface address
hosts = []
sessions = []
commands = []
interface_map = {}
for host in netgraph.graph.nodes:
interface_map[host] = {}
# Build an ordered list of hosts, sessions, and commands
outputs = ssh_helper.run_commands_on_many_hosts(sessions, commands)
for host_idx in range(len(hostnames)):
# Split the output of the `ip` command per-interface. It comes in as a numbered list, so split on the numbers
interface_lines = re.split(r'\s[0-9]+:\s', outputs[host_idx])
# Dump the first line since it is the echo of the command we sent
interface_lines = interface_lines[1:]
for line in interface_lines:
# The first token, ending with a colon, is the name of the interface
interface_name, *remainder = re.split(r':', line, 1)
assert len(remainder) == 1, "Error when splitting for interface name. More than one regex match found!"
if interface_name == 'lo':
# Don't mess with the loopback interface
# Parse out the link-local ipv6 address. There should be only one.
ipaddr = re.findall(r'\sinet6\s+(.*?)\s+scope link', remainder[0])
assert len(ipaddr) == 1, "Should only have found one link-local address!"
ipaddr = ipaddress.ip_interface(ipaddr[0])
interface_map[hostnames[host_idx]][interface_name] = ipaddr
return interface_map
if __name__ == "__main__":
parser = argparse.ArgumentParser("Generate IPv6 Unique Local Addresses for all nodes in the network")
parser.add_argument("--in-file", action='store', type=str, required=True,
help="Path to the NetJSON file to parse")
parser.add_argument("--out-file", action='store', type=str, required=False,
help="Path to write the annotated NetJSON. Default to overwriting in-file.")
parser.add_argument("--username", action='store', type=str, default=getpass.getuser(),
help="Username to use on all hosts. Defaults to current user's username")
args = parser.parse_args()
args.out_file = args.out_file or args.in_file
netgraph = NetJsonParser(file=args.in_file)
hostnames = [node for node in netgraph.graph.nodes]
usernames = [args.username for i in range(len(hostnames))]
sessions, passwords = ssh_helper.log_in_many_sessions(hostnames, usernames)
for host_idx in range(len(hostnames)):
netgraph.graph._node[hostnames[host_idx]]['session'] = sessions[host_idx]
interface_map = parse_local_interface_addresses(netgraph)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment