Commit fa7c1f7e authored by Sigmund Augdal's avatar Sigmund Augdal

Moved api-like code out of neighbors script into a reusable module

parent 094b00ba
......@@ -12,6 +12,7 @@ log = logging.getLogger("neighbors")
from pyroute2.netlink.iproute import IPRoute
import sys
import etcd
from nova_router import neighbors
def byteswap(a):
......@@ -23,15 +24,6 @@ def ifindex(interface):
return int(open("/sys/class/net/{}/ifindex".format(interface)).read().rstrip())
V4 = "ipv4"
V6_LL = "ipv6_ll"
V6_PUB = "ipv6_public"
def etcd_key(mac, addrtype):
return "nova/iaas/instances/{}/{}".format(mac, addrtype)
class NeighborCache(object):
def __init__(self, ssl_cert, ssl_key, cacert, interface, routers):
self.etcd_client = etcd.Etcd(ssl_key=ssl_key, ssl_cert=ssl_cert,
......@@ -40,49 +32,20 @@ class NeighborCache(object):
self.ifindex = ifindex(interface)
self.ir = IPRoute()
self.blacklist_mac = set()
neighbors = self.ir.get_neighbors()
neighbor_events = self.ir.get_neighbors()
addresses = self.ir.get_addr()
addresses = [a.get_attr("IFA_ADDRESS") for a in addresses]
for router in routers:
if router not in addresses:
for n in neighbors:
for n in neighbor_events:
if n.get_attr('NDA_DST') == router:
self.blacklist_mac.add(n.get_attr('NDA_LLADDR').lower())
for np in neighbors:
for np in neighbor_events:
self.process_event(np)
def get_ipaddress_from_mac(self, mac, addrtype):
mac = mac.lower()
try:
return self.etcd_client.get(etcd_key(mac, addrtype)).value
except etcd.EtcdError as ex:
if ex.args[0] == 100:
return None
raise ex
def get_mac_from_ipaddress(self, ipaddress, addrtype):
try:
for entry in self.etcd_client.list("nova/iaas/instances"):
if entry.dir:
mac = entry.key.split("/")[-1]
try:
if self.etcd_client.get(entry.key + "/" + addrtype).value == ipaddress:
return mac
except etcd.EtcdError as ex:
if ex.args[0] != 100:
raise ex
except etcd.EtcdError as ex:
if ex.args[0] == 100:
return None
return None
def add_pair(self, mac, ipaddress, addrtype):
mac = mac.lower()
self.etcd_client.testandset(etcd_key(mac, addrtype), "", ipaddress)
def new(self, mac, ipaddr, addrtype):
mac = mac.lower()
old_address = self.get_ipaddress_from_mac(mac, addrtype)
old_address = neighbors.get_ipaddress_from_mac(self.etcd_client, mac, addrtype)
if not old_address is None:
if old_address == ipaddr:
......@@ -90,9 +53,9 @@ class NeighborCache(object):
else:
log.debug("%s changed address from %s to %s",
mac, old_address, ipaddr)
self.remove(mac, old_address, addrtype)
neighbors.remove_pair(self.etcd_client, mac, old_address, addrtype)
orig_mac = self.get_mac_from_ipaddress(ipaddr, addrtype)
orig_mac = neighbors.get_mac_from_ipaddress(self.etcd_client, ipaddr, addrtype)
if orig_mac is not None:
log.warning("Duplicate address detected."
" %s tries to take %s from %s",
......@@ -100,11 +63,7 @@ class NeighborCache(object):
return
else:
log.debug("New host %s: %s", mac, ipaddr)
self.add_pair(mac, ipaddr, addrtype)
def remove(self, mac, ipaddress, addrtype):
mac = mac.lower()
self.etcd_client.delete(etcd_key(mac, addrtype))
neighbors.add_pair(self.etcd_client, mac, ipaddr, addrtype)
def process_event(self, np):
if np['event'] == 'RTM_NEWNEIGH':
......@@ -118,11 +77,11 @@ class NeighborCache(object):
if mac in self.blacklist_mac:
return
if "." in ip:
addrtype = V4
addrtype = neighbors.V4
elif ip.startswith("fe80"):
addrtype = V6_LL
addrtype = neighbors.V6_LL
else:
addrtype = V6_PUB
addrtype = neighbors.V6_PUB
self.new(mac, ip, addrtype)
def run(self):
......
import etcd
V4 = "ipv4"
V6_LL = "ipv6_ll"
V6_PUB = "ipv6_public"
def etcd_key(mac, addrtype):
return "nova/iaas/instances/{}/{}".format(mac, addrtype)
def get_ipaddress_from_mac(etcd_client, mac, addrtype):
mac = mac.lower()
try:
return etcd_client.get(etcd_key(mac, addrtype)).value
except etcd.EtcdError as ex:
if ex.args[0] == 100:
return None
raise ex
def get_mac_from_ipaddress(etcd_client, ipaddress, addrtype):
try:
for entry in etcd_client.list("nova/iaas/instances"):
if entry.dir:
mac = entry.key.split("/")[-1]
try:
if etcd_client.get(entry.key + "/" + addrtype).value == ipaddress:
return mac
except etcd.EtcdError as ex:
if ex.args[0] != 100:
raise ex
except etcd.EtcdError as ex:
if ex.args[0] == 100:
return None
return None
def add_pair(etcd_client, mac, ipaddress, addrtype):
mac = mac.lower()
etcd_client.testandset(etcd_key(mac, addrtype), "", ipaddress)
def remove_pair(etcd_client, mac, ipaddress, addrtype):
mac = mac.lower()
etcd_client.delete(etcd_key(mac, addrtype))
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