From: Lucas Meneghel Rodrigues <lmr@redhat.com>
To: autotest@test.kernel.org
Cc: kvm@vger.kernel.org
Subject: [PATCH 1/5] KVM test: Adding framework code to control bridge creation
Date: Thu, 2 Jun 2011 01:23:05 -0300 [thread overview]
Message-ID: <1306988589-17085-2-git-send-email-lmr@redhat.com> (raw)
In-Reply-To: <1306988589-17085-1-git-send-email-lmr@redhat.com>
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
Changes from v2:
* Changed firewall rules to match libvirt rules,
made the rules to be added with -I, which will place
them before exclusion rules
* Safer cleanup, always try to cleanup when something
wrong happens during setup.
Signed-off-by: Cleber Rosa <crosa@redhat.com>
Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
Signed-off-by: Amos Kong <akong@redhat.com>
---
client/virt/virt_test_setup.py | 172 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 172 insertions(+), 0 deletions(-)
diff --git a/client/virt/virt_test_setup.py b/client/virt/virt_test_setup.py
index f915c1b..8e69b01 100644
--- a/client/virt/virt_test_setup.py
+++ b/client/virt/virt_test_setup.py
@@ -105,3 +105,175 @@ 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
+ self.iptables_rules = [
+ "INPUT 1 -i %s -p udp -m udp --dport 53 -j ACCEPT" % self.brname,
+ "INPUT 2 -i %s -p tcp -m tcp --dport 53 -j ACCEPT" % self.brname,
+ "INPUT 3 -i %s -p udp -m udp --dport 67 -j ACCEPT" % self.brname,
+ "INPUT 4 -i %s -p tcp -m tcp --dport 67 -j ACCEPT" % self.brname,
+ "INPUT 5 -i %s -p tcp -m tcp --dport 12323 -j ACCEPT" % self.brname,
+ "FORWARD 1 -m physdev --physdev-is-bridged -j ACCEPT",
+ "FORWARD 2 -d %s.0/24 -o %s -m state --state RELATED,ESTABLISHED "
+ "-j ACCEPT" % (self.subnet, self.brname),
+ "FORWARD 3 -s %s.0/24 -i %s -j ACCEPT" % (self.subnet, self.brname),
+ "FORWARD 4 -i %s -o %s -j ACCEPT" % (self.brname, self.brname),
+ ("FORWARD 5 -o %s -j REJECT --reject-with icmp-port-unreachable" %
+ self.brname),
+ ("FORWARD 6 -i %s -j REJECT --reject-with icmp-port-unreachable" %
+ self.brname)]
+
+
+ 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 _iptables_add(self, cmd):
+ return utils.system("iptables -I %s" % cmd)
+
+
+ def _iptables_del(self, cmd):
+ return utils.system("iptables -D %s" % cmd)
+
+
+ def _enable_nat(self):
+ for rule in self.iptables_rules:
+ self._iptables_add(rule)
+
+
+ def _start_dhcp_server(self):
+ utils.system("service dnsmasq stop")
+ utils.system("dnsmasq --strict-order --bind-interfaces "
+ "--listen-address %s.1 --dhcp-range %s.2,%s.254 "
+ "--dhcp-lease-max=253 "
+ "--dhcp-no-override "
+ "--pid-file=/tmp/dnsmasq.pid "
+ "--log-facility=/tmp/dnsmasq.log" %
+ (self.subnet, self.subnet, self.subnet))
+ self.dhcp_server_pid = None
+ 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")
+ for line in brctl_output:
+ if line.startswith(self.brname):
+ logging.critical("%s", len(line.split()))
+ if self.brname not in brctl_output:
+ logging.info("Configuring KVM test private bridge %s", self.brname)
+ try:
+ self._add_bridge()
+ except:
+ self._remove_bridge()
+ raise
+ try:
+ self._bring_bridge_up()
+ except:
+ self._bring_bridge_down()
+ self._remove_bridge()
+ raise
+ try:
+ self._enable_nat()
+ except:
+ self._disable_nat()
+ self._bring_bridge_down()
+ self._remove_bridge()
+ raise
+ try:
+ self._start_dhcp_server()
+ except:
+ self._stop_dhcp_server()
+ self._disable_nat()
+ self._bring_bridge_down()
+ self._remove_bridge()
+ raise
+ self._verify_bridge()
+
+
+ def _stop_dhcp_server(self):
+ if self.dhcp_server_pid is not None:
+ try:
+ os.kill(self.dhcp_server_pid, 15)
+ except OSError:
+ pass
+ else:
+ try:
+ dhcp_server_pid = int(open('/tmp/dnsmasq.pid', 'r').read())
+ except ValueError:
+ return
+ try:
+ os.kill(dhcp_server_pid, 15)
+ except OSError:
+ pass
+
+
+ def _bring_bridge_down(self):
+ utils.system("ifconfig %s down" % self.brname, ignore_status=True)
+
+
+ def _disable_nat(self):
+ for rule in self.iptables_rules:
+ split_list = rule.split(' ')
+ # We need to remove numbering here
+ split_list.pop(1)
+ rule = " ".join(split_list)
+ self._iptables_del(rule)
+
+
+ def _remove_bridge(self):
+ utils.system("brctl delbr %s" % self.brname, ignore_status=True)
+
+
+ def cleanup(self):
+ brctl_output = utils.system_output("brctl show")
+ cleanup = False
+ for line in brctl_output.split("\n"):
+ if line.startswith(self.brname):
+ # len == 4 means there is a TAP using the bridge
+ # so don't try to clean it up
+ if len(line.split()) < 4:
+ cleanup = True
+ break
+ if cleanup:
+ logging.debug("Cleaning up KVM test private bridge %s", self.brname)
+ self._stop_dhcp_server()
+ self._disable_nat()
+ self._bring_bridge_down()
+ self._remove_bridge()
--
1.7.5.2
next prev parent reply other threads:[~2011-06-02 4:23 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-02 4:23 [PATCH 0/5] Create private bridge, get rid of qemu ifup scripts v3 Lucas Meneghel Rodrigues
2011-06-02 4:23 ` Lucas Meneghel Rodrigues [this message]
2011-06-02 4:23 ` [PATCH 2/5] KVM test: Add helpers to control the TAP/bridge Lucas Meneghel Rodrigues
2011-06-02 4:23 ` [PATCH 3/5] KVM test: virt_env_process: Setup private bridge during postprocessing Lucas Meneghel Rodrigues
2011-06-02 4:23 ` [PATCH 4/5] KVM test: setup tap fd and pass it to qemu-kvm v3 Lucas Meneghel Rodrigues
2011-06-02 4:23 ` [PATCH 5/5] KVM test: Changing KVM autotest default to private bridge Lucas Meneghel Rodrigues
2011-06-06 17:29 ` [PATCH 0/5] Create private bridge, get rid of qemu ifup scripts v3 Lucas Meneghel Rodrigues
-- strict thread matches above, loose matches on Subject: below --
2011-05-24 7:03 [PATCH 0/5] Setup private bridge in KVM autotest, get rid of ifup scripts Lucas Meneghel Rodrigues
2011-05-24 7:03 ` [PATCH 1/5] KVM test: Adding framework code to control bridge creation Lucas Meneghel Rodrigues
2011-05-21 4:23 [PATCH 0/5] Setup private bridge in KVM autotest, get rid of ifup scripts Lucas Meneghel Rodrigues
2011-05-21 4:23 ` [PATCH 1/5] KVM test: Adding framework code to control bridge creation Lucas Meneghel Rodrigues
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1306988589-17085-2-git-send-email-lmr@redhat.com \
--to=lmr@redhat.com \
--cc=autotest@test.kernel.org \
--cc=kvm@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox