Provide in framework utility code to control the creation of a bridge, in order to provide TAP functionality for autotest users without relying on previous setup made by the user. This is a reimplementation of Amos's code, the differences are: * Implemented as a setup class, taking advantage of object internal state to use in different places of the code * Split up the operations to make it easier to understand the steps and why we are doing them * Use of autotest API instead of commands Signed-off-by: Lucas Meneghel Rodrigues <lmr@xxxxxxxxxx> Signed-off-by: Amos Kong <akong@xxxxxxxxxx> --- client/virt/virt_test_setup.py | 103 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 103 insertions(+), 0 deletions(-) diff --git a/client/virt/virt_test_setup.py b/client/virt/virt_test_setup.py index f915c1b..cdc0e23 100644 --- a/client/virt/virt_test_setup.py +++ b/client/virt/virt_test_setup.py @@ -105,3 +105,106 @@ class HugePageConfig(object): return utils.system("echo 0 > %s" % self.kernel_hp_file) logging.debug("Hugepage memory successfuly dealocated") + + +class PrivateBridgeError(Exception): + def __init__(self, brname): + self.brname = brname + + def __str__(self): + return "Bridge %s not available after setup" % self.brname + + +class PrivateBridgeConfig(object): + __shared_state = {} + def __init__(self, params=None): + self.__dict__ = self.__shared_state + if params is not None: + self.brname = params.get("priv_brname", 'atbr0') + self.subnet = params.get("priv_subnet", '192.168.58') + self.ip_version = params.get("bridge_ip_version", "ipv4") + self.dhcp_server_pid = None + + + def _add_bridge(self): + utils.system("brctl addbr %s" % self.brname) + ip_fwd_path = "/proc/sys/net/%s/ip_forward" % self.ip_version + ip_fwd = open(ip_fwd_path, "w") + ip_fwd.write("1\n") + utils.system("brctl stp %s on" % self.brname) + utils.system("brctl setfd %s 0" % self.brname) + + + def _bring_bridge_up(self): + utils.system("ifconfig %s %s.1 up" % (self.brname, self.subnet)) + + + def _enable_nat(self): + utils.system("iptables -t nat -A POSTROUTING -s %s.254/24 ! " + "-d %s.254/24 -j MASQUERADE" % (self.subnet, self.subnet)) + + + def _start_dhcp_server(self): + utils.system("service dnsmasq stop") + utils.system("dnsmasq --strict-order --bind-interfaces " + "--listen-address %s.1 --dhcp-range %s.1,%s.254 " + "--pid-file=/tmp/dnsmasq.pid " + "--log-facility=/tmp/dnsmasq.log" % + (self.subnet, self.subnet, self.subnet)) + try: + self.dhcp_server_pid = int(open('/tmp/dnsmasq.pid', 'r').read()) + except ValueError: + raise PrivateBridgeError(self.brname) + logging.debug("Started internal DHCP server with PID %s", + self.dhcp_server_pid) + + + def _verify_bridge(self): + brctl_output = utils.system_output("brctl show") + if self.brname not in brctl_output: + raise PrivateBridgeError(self.brname) + + + def setup(self): + brctl_output = utils.system_output("brctl show") + if self.brname not in brctl_output: + logging.info("Configuring KVM test private bridge %s", self.brname) + self._add_bridge() + self._bring_bridge_up() + self._enable_nat() + self._start_dhcp_server() + self._verify_bridge() + + + def _stop_dhcp_server(self): + os.kill(self.dhcp_server_pid, 15) + + + def _bring_bridge_down(self): + utils.system("ifconfig %s down" % self.brname) + + + def _disable_nat(self): + utils.system("iptables -t nat -D POSTROUTING -s %s.254/24 !" + " -d %s.254/24 -j MASQUERADE" % (self.subnet, self.subnet)) + + + def _remove_bridge(self): + utils.system("brctl delbr %s" % self.brname) + + + def cleanup(self): + brctl_output = utils.system_output("brctl show") + cleanup = False + for line in brctl_output: + if line.startswith(self.brname): + # len == 4 means there is a TAP using the bridge + # so don't try to clean up + if len(line.split()) < 4: + cleanup = True + if cleanup: + logging.debug("Cleaning up KVM test private bridge %s", self.brname) + self._stop_dhcp_server() + self._bring_bridge_down() + self._disable_nat() + self._remove_bridge() -- 1.7.5.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html