From: Jiri Pirko <jiri(a)mellanox.com>
This patch allows LNST tasks to create on-fly soft-devices. So far,
bridge, bonds, teams and vlans are supported. It is easy to extend this
to all devices supported by LNST.
This allows user to define machine network config in Task like in
following example:
-------------------------------------------------------------------------------
from lnst.Controller.Task import ctl
m1 = ctl.get_host("machine1")
if1 = m1.get_interface("if1")
if2 = m1.get_interface("if2")
if3 = m1.get_interface("if3")
team_config = '{"runner" : {"name" : "lacp"}}'
team_if1_config = '{"prio": 11}'
team = m1.create_team(slaves=[(if1, team_if1_config), if2], config=team_config)
br = m1.create_bridge(slaves=[if3, team], options={"stp_state": 0})
vlan = m1.create_vlan(br, 100, ip="192.168.45.3/24")
-------------------------------------------------------------------------------
As you can see, it is quite easy and intuitive.
Next step is to allow device destruction in Tasks. Should be quite easy
to implement as well. That would allow on-fly change of network
configuration for running tasks.
This allows to reduce LNST xml recipes to just plain definition of
physical devices used for match. Next step is to allow to do this
definition of physical devices in so-called python-recipe. That would
allow user to use pure-python LNST recipes and tasks. Cool, isn't it?
Signed-off-by: Jiri Pirko <jiri(a)mellanox.com>
---
lnst/Controller/Task.py | 76 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/lnst/Controller/Task.py b/lnst/Controller/Task.py
index 242d046..990e013 100644
--- a/lnst/Controller/Task.py
+++ b/lnst/Controller/Task.py
@@ -363,6 +363,82 @@ class HostAPI(object):
self._m.sync_resources(sync_table)
+ def _generate_if_id(self, if_type):
+ i = 0
+ while True:
+ if_id = "task_%s_%d" % (if_type, i)
+ if not if_id in self._ifaces:
+ break
+ i += 1
+ return if_id
+
+ def _add_iface(self, if_type, if_id, netns, ip, options, slaves):
+ if not if_id:
+ if_id = self._generate_if_id(if_type)
+ interface = self._m.new_soft_interface(if_id, if_type)
+ iface = InterfaceAPI(interface, self)
+ self._ifaces[if_id] = iface
+
+ if slaves:
+ for slave in slaves:
+ if type(slave) == type(()):
+ slave_iface = slave[0]
+ slave_options = slave[1]
+ for key in slave_options:
+ interface.set_slave_option(slave_iface.get_id(),
+ key, slave_options[key])
+ else:
+ slave_iface = slave
+ interface.add_slave(slave_iface._if)
+
+ if ip:
+ if (type(ip) == type([])):
+ for one_ip in ip:
+ interface.add_address(one_ip)
+ else:
+ interface.add_address(ip)
+
+ if options:
+ for key in options:
+ interface.set_option(key, options[key])
+
+ if netns:
+ interface.set_netns(netns)
+
+ interface.configure()
+ interface.up()
+ return iface
+
+ def create_bond(self, if_id=None, netns=None, ip=None,
+ options=None, slaves=None):
+ return self._add_iface("bond", if_id, netns, ip, options, slaves)
+
+ def create_bridge(self, if_id=None, netns=None, ip=None,
+ options=None, slaves=None):
+ return self._add_iface("bridge", if_id, netns, ip, options, slaves)
+
+ def create_team(self, config=None, if_id=None, netns=None, ip=None,
+ slaves=None):
+ out_slaves = []
+ for slave in slaves:
+ if type(slave) == type(()):
+ slave_iface = slave[0]
+ slave_config = slave[1]
+ out_slaves.append((slave_iface,
+ {"teamd_port_config": slave_config}))
+ else:
+ out_slaves.append(slave)
+
+ options = {}
+ if config:
+ options["teamd_config"] = config
+
+ return self._add_iface("team", if_id, netns, ip, options, out_slaves)
+
+ def create_vlan(self, realdev_iface, vlan_tci, ip=None, if_id=None, netns=None):
+ return self._add_iface("vlan", if_id, netns, ip, {"vlan_tci":
vlan_tci},
+ [realdev_iface])
+
class InterfaceAPI(object):
def __init__(self, interface, host):
self._if = interface
--
2.4.3