Extracting common code to trellis library

Change-Id: Iaa3170bb7679a273473bb3459082121e465907ea
diff --git a/trellis/trellis.py b/trellis/trellis.py
index 78cdc7b..2fab97b 100755
--- a/trellis/trellis.py
+++ b/trellis/trellis.py
@@ -11,6 +11,7 @@
 from ipaddress import ip_network
 from routinglib import BgpRouter
 from routinglib import RoutedHost
+from trellislib import DhcpClient, DhcpServer
 
 class Trellis( Topo ):
     "Trellis basic topology"
@@ -96,35 +97,6 @@
 
 topos = { 'trellis' : Trellis }
 
-class DhcpClient(Host):
-    def __init__(self, name, *args, **kwargs):
-        super(DhcpClient, self).__init__(name, **kwargs)
-        self.pidFile = '/run/dhclient-%s.pid' % self.name
-
-    def config(self, **kwargs):
-        super(DhcpClient, self).config(**kwargs)
-        self.cmd('ip addr flush dev %s' % self.defaultIntf())
-        self.cmd('dhclient -q -4 -nw -pf %s %s' % (self.pidFile, self.defaultIntf()))
-
-    def terminate(self, **kwargs):
-        self.cmd('kill -9 `cat %s`' % self.pidFile)
-        self.cmd('rm -rf %s' % self.pidFile)
-        super(DhcpClient, self).terminate()
-
-class DhcpServer(RoutedHost):
-    binFile = '/usr/sbin/dhcpd'
-    pidFile = '/run/dhcp-server/dhcpd.pid'
-    configFile = './dhcpd.conf'
-
-    def config(self, **kwargs):
-        super(DhcpServer, self).config(**kwargs)
-        self.cmd('%s -q -4 -pf %s -cf %s %s' % (self.binFile, self.pidFile, self.configFile, self.defaultIntf()))
-
-    def terminate(self, **kwargs):
-        self.cmd('kill -9 `cat %s`' % self.pidFile)
-        self.cmd('rm -rf %s' % self.pidFile)
-        super(DhcpServer, self).terminate()
-
 if __name__ == "__main__":
     setLogLevel('debug')
     topo = Trellis()
diff --git a/trellis/trellis_dualhome.py b/trellis/trellis_dualhome.py
index 1383cc9..598c4f5 100755
--- a/trellis/trellis_dualhome.py
+++ b/trellis/trellis_dualhome.py
@@ -12,6 +12,8 @@
 from ipaddress import ip_network
 from routinglib import BgpRouter
 from routinglib import RoutedHost
+from trellislib import DhcpClient, DhcpServer
+from trellislib import DualHomedDhcpClient
 
 class Trellis( Topo ):
     "Trellis basic topology"
@@ -120,65 +122,6 @@
 
 topos = { 'trellis' : Trellis }
 
-# TODO extract dhcp classes to a separate library
-class DhcpClient(Host):
-    def __init__(self, name, *args, **kwargs):
-        super(DhcpClient, self).__init__(name, **kwargs)
-        self.pidFile = '/run/dhclient-%s.pid' % self.name
-
-    def config(self, **kwargs):
-        super(DhcpClient, self).config(**kwargs)
-        self.cmd('ip addr flush dev %s' % self.defaultIntf())
-        self.cmd('dhclient -q -4 -nw -pf %s %s' % (self.pidFile, self.defaultIntf()))
-
-    def terminate(self, **kwargs):
-        self.cmd('kill -9 `cat %s`' % self.pidFile)
-        self.cmd('rm -rf %s' % self.pidFile)
-        super(DhcpClient, self).terminate()
-
-class DualHomedDhcpClient(Host):
-    def __init__(self, name, *args, **kwargs):
-        super(DualHomedDhcpClient, self).__init__(name, **kwargs)
-        self.pidFile = '/run/dhclient-%s.pid' % self.name
-        self.bond0 = None
-
-    def config(self, **kwargs):
-        super(DualHomedDhcpClient, self).config(**kwargs)
-        intf0 = self.intfs[0].name
-        intf1 = self.intfs[1].name
-        self.bond0 = "%s-bond0" % self.name
-        self.cmd('modprobe bonding')
-        self.cmd('ip link add %s type bond' % self.bond0)
-        self.cmd('ip link set %s down' % intf0)
-        self.cmd('ip link set %s down' % intf1)
-        self.cmd('ip link set %s master %s' % (intf0, self.bond0))
-        self.cmd('ip link set %s master %s' % (intf1, self.bond0))
-        self.cmd('ip addr flush dev %s' % intf0)
-        self.cmd('ip addr flush dev %s' % intf1)
-        self.cmd('ip link set %s up' % self.bond0)
-        self.cmd('dhclient -q -4 -nw -pf %s %s' % (self.pidFile, self.bond0))
-
-    def terminate(self, **kwargs):
-        self.cmd('ip link set %s down' % self.bond0)
-        self.cmd('ip link delete %s' % self.bond0)
-        self.cmd('kill -9 `cat %s`' % self.pidFile)
-        self.cmd('rm -rf %s' % self.pidFile)
-        super(DualHomedDhcpClient, self).terminate()
-
-class DhcpServer(RoutedHost):
-    binFile = '/usr/sbin/dhcpd'
-    pidFile = '/run/dhcp-server/dhcpd.pid'
-    configFile = './dhcpd.conf'
-
-    def config(self, **kwargs):
-        super(DhcpServer, self).config(**kwargs)
-        self.cmd('%s -q -4 -pf %s -cf %s %s' % (self.binFile, self.pidFile, self.configFile, self.defaultIntf()))
-
-    def terminate(self, **kwargs):
-        self.cmd('kill -9 `cat %s`' % self.pidFile)
-        self.cmd('rm -rf %s' % self.pidFile)
-        super(DhcpServer, self).terminate()
-
 if __name__ == "__main__":
     setLogLevel('debug')
     topo = Trellis()
diff --git a/trellis/trellis_remote_dhcp.py b/trellis/trellis_remote_dhcp.py
index 73bc8f3..606935e 100755
--- a/trellis/trellis_remote_dhcp.py
+++ b/trellis/trellis_remote_dhcp.py
@@ -11,6 +11,7 @@
 from ipaddress import ip_network
 from routinglib import BgpRouter
 from routinglib import RoutedHost
+from trellislib import DhcpClient, DhcpServer
 
 class Trellis( Topo ):
     "Trellis basic topology"
@@ -100,35 +101,6 @@
 
 topos = { 'trellis' : Trellis }
 
-class DhcpClient(Host):
-    def __init__(self, name, *args, **kwargs):
-        super(DhcpClient, self).__init__(name, **kwargs)
-        self.pidFile = '/run/dhclient-%s.pid' % self.name
-
-    def config(self, **kwargs):
-        super(DhcpClient, self).config(**kwargs)
-        self.cmd('ip addr flush dev %s' % self.defaultIntf())
-        self.cmd('dhclient -q -4 -nw -pf %s %s' % (self.pidFile, self.defaultIntf()))
-
-    def terminate(self, **kwargs):
-        self.cmd('kill -9 `cat %s`' % self.pidFile)
-        self.cmd('rm -rf %s' % self.pidFile)
-        super(DhcpClient, self).terminate()
-
-class DhcpServer(RoutedHost):
-    binFile = '/usr/sbin/dhcpd'
-    pidFile = '/run/dhcp-server/dhcpd.pid'
-    configFile = './dhcpd.conf'
-
-    def config(self, **kwargs):
-        super(DhcpServer, self).config(**kwargs)
-        self.cmd('%s -q -4 -pf %s -cf %s %s' % (self.binFile, self.pidFile, self.configFile, self.defaultIntf()))
-
-    def terminate(self, **kwargs):
-        self.cmd('kill -9 `cat %s`' % self.pidFile)
-        self.cmd('rm -rf %s' % self.pidFile)
-        super(DhcpServer, self).terminate()
-
 if __name__ == "__main__":
     setLogLevel('debug')
     topo = Trellis()
diff --git a/trellis/trellis_vlan.py b/trellis/trellis_vlan.py
index 5621672..e8caf95 100755
--- a/trellis/trellis_vlan.py
+++ b/trellis/trellis_vlan.py
@@ -11,6 +11,8 @@
 from ipaddress import ip_network
 from routinglib import BgpRouter
 from routinglib import RoutedHost
+from trellislib import DhcpClient, DhcpServer
+from trellislib import TaggedDhcpClient, TaggedDhcpServer
 
 class Trellis( Topo ):
     "Trellis basic topology"
@@ -99,95 +101,6 @@
 
 topos = { 'trellis' : Trellis }
 
-class DhcpClient(Host):
-    def __init__(self, name, *args, **kwargs):
-        super(DhcpClient, self).__init__(name, **kwargs)
-        self.pidFile = '/run/dhclient-%s.pid' % self.name
-
-    def config(self, **kwargs):
-        super(DhcpClient, self).config(**kwargs)
-        self.cmd('ip addr flush dev %s' % self.defaultIntf())
-        self.cmd('dhclient -q -4 -nw -pf %s %s' % (self.pidFile, self.defaultIntf()))
-
-    def terminate(self, **kwargs):
-        self.cmd('kill -9 `cat %s`' % self.pidFile)
-        self.cmd('rm -rf %s' % self.pidFile)
-        super(DhcpClient, self).terminate()
-
-class TaggedDhcpClient(Host):
-    def __init__(self, name, vlan, *args, **kwargs):
-        super(TaggedDhcpClient, self).__init__(name, **kwargs)
-        self.pidFile = '/run/dhclient-%s.pid' % self.name
-        self.vlan = vlan
-        self.vlanIntf = None
-
-    def config(self, **kwargs):
-        super(TaggedDhcpClient, self).config(**kwargs)
-        self.vlanIntf = "%s.%s" % (self.defaultIntf(), self.vlan)
-        self.cmd('ip addr flush dev %s' % self.defaultIntf())
-        self.cmd('ip link add link %s name %s type vlan id %s' % (self.defaultIntf(), self.vlanIntf, self.vlan))
-        self.cmd('ip link set up %s' % self.vlanIntf)
-        self.cmd('dhclient -q -4 -nw -pf %s %s' % (self.pidFile, self.vlanIntf))
-
-    def terminate(self, **kwargs):
-        self.cmd('kill -9 `cat %s`' % self.pidFile)
-        self.cmd('rm -rf %s' % self.pidFile)
-        self.cmd('ip link remove link %s' % self.vlanIntf)
-        super(TaggedDhcpClient, self).terminate()
-
-class DhcpServer(RoutedHost):
-    binFile = '/usr/sbin/dhcpd'
-    pidFile = '/run/dhcp-server/dhcpd.pid'
-    configFile = './dhcpd.conf'
-
-    def config(self, **kwargs):
-        super(DhcpServer, self).config(**kwargs)
-        self.cmd('%s -q -4 -pf %s -cf %s %s' % (self.binFile, self.pidFile, self.configFile, self.defaultIntf()))
-
-    def terminate(self, **kwargs):
-        self.cmd('kill -9 `cat %s`' % self.pidFile)
-        self.cmd('rm -rf %s' % self.pidFile)
-        super(DhcpServer, self).terminate()
-
-class TaggedRoutedHost(RoutedHost):
-    """Host that can be configured with multiple IP addresses."""
-    def __init__(self, name, ips, gateway, vlan, *args, **kwargs):
-        super(RoutedHost, self).__init__(name, *args, **kwargs)
-        self.ips = ips
-        self.gateway = gateway
-        self.vlan = vlan
-        self.vlanIntf = None
-
-    def config(self, **kwargs):
-        Host.config(self, **kwargs)
-        self.vlanIntf = "%s.%s" % (self.defaultIntf(), self.vlan)
-        self.cmd('ip -4 addr flush dev %s' % self.defaultIntf())
-        self.cmd('ip link add link %s name %s type vlan id %s' % (self.defaultIntf(), self.vlanIntf, self.vlan))
-        self.cmd('ip link set up %s' % self.vlanIntf)
-
-        for ip in self.ips:
-            self.cmd('ip addr add %s dev %s' % (ip, self.vlanIntf))
-
-        self.cmd('ip route add default via %s' % self.gateway)
-
-    def terminate(self, **kwargs):
-        self.cmd('ip link remove link %s' % self.vlanIntf)
-        super(TaggedRoutedHost, self).terminate()
-
-class TaggedDhcpServer(TaggedRoutedHost):
-    binFile = '/usr/sbin/dhcpd'
-    pidFile = '/run/dhcp-server/dhcpd.pid'
-    configFile = './dhcpd.conf'
-
-    def config(self, **kwargs):
-        super(TaggedDhcpServer, self).config(**kwargs)
-        self.cmd('%s -q -4 -pf %s -cf %s %s' % (self.binFile, self.pidFile, self.configFile, self.vlanIntf))
-
-    def terminate(self, **kwargs):
-        self.cmd('kill -9 `cat %s`' % self.pidFile)
-        self.cmd('rm -rf %s' % self.pidFile)
-        super(TaggedDhcpServer, self).terminate()
-
 if __name__ == "__main__":
     setLogLevel('debug')
     topo = Trellis()
diff --git a/trellis/trellislib.py b/trellis/trellislib.py
new file mode 100644
index 0000000..6bff4cc
--- /dev/null
+++ b/trellis/trellislib.py
@@ -0,0 +1,128 @@
+#!/usr/bin/python
+
+"""
+Libraries for Trellis hosts.
+"""
+
+import sys
+sys.path.append('..')
+from mininet.node import Host
+from routinglib import RoutedHost
+
+class TaggedRoutedHost(RoutedHost):
+    """Host that can be configured with multiple IP addresses."""
+    def __init__(self, name, ips, gateway, vlan, *args, **kwargs):
+        super(RoutedHost, self).__init__(name, *args, **kwargs)
+        self.ips = ips
+        self.gateway = gateway
+        self.vlan = vlan
+        self.vlanIntf = None
+
+    def config(self, **kwargs):
+        Host.config(self, **kwargs)
+        self.vlanIntf = "%s.%s" % (self.defaultIntf(), self.vlan)
+        self.cmd('ip -4 addr flush dev %s' % self.defaultIntf())
+        self.cmd('ip link add link %s name %s type vlan id %s' % (self.defaultIntf(), self.vlanIntf, self.vlan))
+        self.cmd('ip link set up %s' % self.vlanIntf)
+
+        for ip in self.ips:
+            self.cmd('ip addr add %s dev %s' % (ip, self.vlanIntf))
+
+        self.cmd('ip route add default via %s' % self.gateway)
+
+    def terminate(self, **kwargs):
+        self.cmd('ip link remove link %s' % self.vlanIntf)
+        super(TaggedRoutedHost, self).terminate()
+
+class DhcpClient(Host):
+    def __init__(self, name, *args, **kwargs):
+        super(DhcpClient, self).__init__(name, **kwargs)
+        self.pidFile = '/run/dhclient-%s.pid' % self.name
+
+    def config(self, **kwargs):
+        super(DhcpClient, self).config(**kwargs)
+        self.cmd('ip addr flush dev %s' % self.defaultIntf())
+        self.cmd('dhclient -q -4 -nw -pf %s %s' % (self.pidFile, self.defaultIntf()))
+
+    def terminate(self, **kwargs):
+        self.cmd('kill -9 `cat %s`' % self.pidFile)
+        self.cmd('rm -rf %s' % self.pidFile)
+        super(DhcpClient, self).terminate()
+
+class DhcpServer(RoutedHost):
+    binFile = '/usr/sbin/dhcpd'
+    pidFile = '/run/dhcp-server/dhcpd.pid'
+    configFile = './dhcpd.conf'
+
+    def config(self, **kwargs):
+        super(DhcpServer, self).config(**kwargs)
+        self.cmd('%s -q -4 -pf %s -cf %s %s' % (self.binFile, self.pidFile, self.configFile, self.defaultIntf()))
+
+    def terminate(self, **kwargs):
+        self.cmd('kill -9 `cat %s`' % self.pidFile)
+        self.cmd('rm -rf %s' % self.pidFile)
+        super(DhcpServer, self).terminate()
+
+class TaggedDhcpClient(Host):
+    def __init__(self, name, vlan, *args, **kwargs):
+        super(TaggedDhcpClient, self).__init__(name, **kwargs)
+        self.pidFile = '/run/dhclient-%s.pid' % self.name
+        self.vlan = vlan
+        self.vlanIntf = None
+
+    def config(self, **kwargs):
+        super(TaggedDhcpClient, self).config(**kwargs)
+        self.vlanIntf = "%s.%s" % (self.defaultIntf(), self.vlan)
+        self.cmd('ip addr flush dev %s' % self.defaultIntf())
+        self.cmd('ip link add link %s name %s type vlan id %s' % (self.defaultIntf(), self.vlanIntf, self.vlan))
+        self.cmd('ip link set up %s' % self.vlanIntf)
+        self.cmd('dhclient -q -4 -nw -pf %s %s' % (self.pidFile, self.vlanIntf))
+
+    def terminate(self, **kwargs):
+        self.cmd('kill -9 `cat %s`' % self.pidFile)
+        self.cmd('rm -rf %s' % self.pidFile)
+        self.cmd('ip link remove link %s' % self.vlanIntf)
+        super(TaggedDhcpClient, self).terminate()
+
+class TaggedDhcpServer(TaggedRoutedHost):
+    binFile = '/usr/sbin/dhcpd'
+    pidFile = '/run/dhcp-server/dhcpd.pid'
+    configFile = './dhcpd.conf'
+
+    def config(self, **kwargs):
+        super(TaggedDhcpServer, self).config(**kwargs)
+        self.cmd('%s -q -4 -pf %s -cf %s %s' % (self.binFile, self.pidFile, self.configFile, self.vlanIntf))
+
+    def terminate(self, **kwargs):
+        self.cmd('kill -9 `cat %s`' % self.pidFile)
+        self.cmd('rm -rf %s' % self.pidFile)
+        super(TaggedDhcpServer, self).terminate()
+
+class DualHomedDhcpClient(Host):
+    def __init__(self, name, *args, **kwargs):
+        super(DualHomedDhcpClient, self).__init__(name, **kwargs)
+        self.pidFile = '/run/dhclient-%s.pid' % self.name
+        self.bond0 = None
+
+    def config(self, **kwargs):
+        super(DualHomedDhcpClient, self).config(**kwargs)
+        intf0 = self.intfs[0].name
+        intf1 = self.intfs[1].name
+        self.bond0 = "%s-bond0" % self.name
+        self.cmd('modprobe bonding')
+        self.cmd('ip link add %s type bond' % self.bond0)
+        self.cmd('ip link set %s down' % intf0)
+        self.cmd('ip link set %s down' % intf1)
+        self.cmd('ip link set %s master %s' % (intf0, self.bond0))
+        self.cmd('ip link set %s master %s' % (intf1, self.bond0))
+        self.cmd('ip addr flush dev %s' % intf0)
+        self.cmd('ip addr flush dev %s' % intf1)
+        self.cmd('ip link set %s up' % self.bond0)
+        self.cmd('dhclient -q -4 -nw -pf %s %s' % (self.pidFile, self.bond0))
+
+    def terminate(self, **kwargs):
+        self.cmd('ip link set %s down' % self.bond0)
+        self.cmd('ip link delete %s' % self.bond0)
+        self.cmd('kill -9 `cat %s`' % self.pidFile)
+        self.cmd('rm -rf %s' % self.pidFile)
+        super(DualHomedDhcpClient, self).terminate()