From: Ondrej Lichtner <olichtne(a)redhat.com>
InterfaceManager and Device objects are now capable of handling ip
address related netlink messages. The Device object stores addresses in
a list as dictionaries. This should change in the future to either use
the Python ipaddress module or to use our own custom objects for ip
addresses.
Additionally the Device objects now generate an update message for the
controller in the init_netlink method as well and we'll be sending an
update message for all devices, even ones that aren't mapped based on
the currently running recipe.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Slave/InterfaceManager.py | 76 +++++++++++++++++++++++++++++++++---------
1 file changed, 60 insertions(+), 16 deletions(-)
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py
index edeb5bc..1999ed8 100644
--- a/lnst/Slave/InterfaceManager.py
+++ b/lnst/Slave/InterfaceManager.py
@@ -24,9 +24,13 @@ from pyroute2 import IPRSocket
try:
from pyroute2.netlink.iproute import RTM_NEWLINK
from pyroute2.netlink.iproute import RTM_DELLINK
+ from pyroute2.netlink.iproute import RTM_NEWADDR
+ from pyroute2.netlink.iproute import RTM_DELADDR
except ImportError:
from pyroute2.iproute import RTM_NEWLINK
from pyroute2.iproute import RTM_DELLINK
+ from pyroute2.iproute import RTM_NEWADDR
+ from pyroute2.iproute import RTM_DELADDR
class IfMgrError(Exception):
pass
@@ -95,7 +99,7 @@ class InterfaceManager(object):
self._handle_netlink_msg(msg)
def _handle_netlink_msg(self, msg):
- if msg['header']['type'] == RTM_NEWLINK:
+ if msg['header']['type'] in [RTM_NEWLINK, RTM_NEWADDR,
RTM_DELADDR]:
if msg['index'] in self._devices:
update_msg = self._devices[msg['index']].update_netlink(msg)
if update_msg != None:
@@ -103,9 +107,8 @@ class InterfaceManager(object):
if if_index == msg['index']:
update_msg["if_id"] = if_id
break
- if "if_id" in update_msg:
- self._server_handler.send_data_to_ctl(update_msg)
- else:
+ self._server_handler.send_data_to_ctl(update_msg)
+ elif msg['header']['type'] == RTM_NEWLINK:
dev = None
for if_id, d in self._tmp_mapping.items():
d_cfg = d.get_conf_dict()
@@ -116,8 +119,16 @@ class InterfaceManager(object):
break
if dev == None:
dev = Device(self)
- dev.init_netlink(msg)
+ update_msg = dev.init_netlink(msg)
self._devices[msg['index']] = dev
+
+ if update_msg != None:
+ for if_id, if_index in self._id_mapping.iteritems():
+ if if_index == msg['index']:
+ update_msg["if_id"] = if_id
+ break
+ self._server_handler.send_data_to_ctl(update_msg)
+
elif msg['header']['type'] == RTM_DELLINK:
if msg['index'] in self._devices:
dev = self._devices[msg['index']]
@@ -294,7 +305,7 @@ class Device(object):
self._name = None
self._conf = None
self._conf_dict = None
- self._ip = None
+ self._ip_addrs = []
self._ifi_type = None
self._state = None
self._master = {"primary": None, "other": []}
@@ -312,7 +323,7 @@ class Device(object):
self._hwaddr = normalize_hwaddr(nl_msg.get_attr("IFLA_ADDRESS"))
self._name = nl_msg.get_attr("IFLA_IFNAME")
self._state = nl_msg.get_attr("IFLA_OPERSTATE")
- self._ip = None #TODO
+ self._ip_addrs = []
self.set_master(nl_msg.get_attr("IFLA_MASTER"), primary=True)
self._netns = None
self._mtu = nl_msg.get_attr("IFLA_MTU")
@@ -322,13 +333,18 @@ class Device(object):
self._initialized = True
+ #return an update message that will be sent to the controller
+ return {"type": "if_update",
+ "if_data": self.get_if_data()}
+
def update_netlink(self, nl_msg):
- if self._if_index == nl_msg['index']:
+ if self._if_index != nl_msg['index']:
+ return None
+ if nl_msg['header']['type'] == RTM_NEWLINK:
self._ifi_type = nl_msg['ifi_type']
self._hwaddr = normalize_hwaddr(nl_msg.get_attr("IFLA_ADDRESS"))
self._name = nl_msg.get_attr("IFLA_IFNAME")
self._state = nl_msg.get_attr("IFLA_OPERSTATE")
- self._ip = None #TODO
self.set_master(nl_msg.get_attr("IFLA_MASTER"), primary=True)
self._mtu = nl_msg.get_attr("IFLA_MTU")
@@ -354,11 +370,29 @@ class Device(object):
self._driver = self._ethtool_get_driver()
self._initialized = True
-
- #return an update message that will be sent to the controller
- return {"type": "if_update",
- "if_data": self.get_if_data()}
- return None
+ elif nl_msg['header']['type'] == RTM_NEWADDR:
+ scope = nl_msg['scope']
+ addr_val = nl_msg.get_attr('IFA_ADDRESS')
+ prefix_len = str(nl_msg['prefixlen'])
+ addr = {"addr": addr_val,
+ "prefix": prefix_len,
+ "scope": scope}
+ if self.find_addrs(addr) == []:
+ self._ip_addrs.append(addr)
+ elif nl_msg['header']['type'] == RTM_DELADDR:
+ scope = nl_msg['scope']
+ addr_val = nl_msg.get_attr('IFA_ADDRESS')
+ prefix_len = str(nl_msg['prefixlen'])
+ addr = {"addr": addr_val,
+ "prefix": prefix_len,
+ "scope": scope}
+ matching_addrs = self.find_addrs(addr)
+ for ip_addr in matching_addrs:
+ self._ip_addrs.remove(ip_addr)
+
+ #return an update message that will be sent to the controller
+ return {"type": "if_update",
+ "if_data": self.get_if_data()}
def del_link(self):
if self._master["primary"]:
@@ -377,6 +411,13 @@ class Device(object):
if dev != None:
dev.del_master(self._if_index)
+ def find_addrs(self, addr_spec):
+ ret = []
+ for addr in self._ip_addrs:
+ if addr_spec.viewitems() <= addr.viewitems():
+ ret.append(addr)
+ return ret
+
def get_if_index(self):
return self._if_index
@@ -386,8 +427,11 @@ class Device(object):
def get_name(self):
return self._name
- def get_ip_conf(self):
- return self._ip
+ def get_ips(self):
+ return self._ip_addrs
+
+ def clear_ips(self):
+ self._ip_addrs = []
def is_configured(self):
return self._configured
--
2.8.2