From patchwork Wed Oct 3 12:10:34 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jiri Zupka X-Patchwork-Id: 1541251 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 4F845DFF71 for ; Wed, 3 Oct 2012 12:11:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754164Ab2JCMLO (ORCPT ); Wed, 3 Oct 2012 08:11:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36726 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754127Ab2JCMLL (ORCPT ); Wed, 3 Oct 2012 08:11:11 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q93CAob1015113 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 3 Oct 2012 08:10:50 -0400 Received: from jzupka-pc.local.com (dhcp-26-117.brq.redhat.com [10.34.26.117]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q93CAgif031379; Wed, 3 Oct 2012 08:10:48 -0400 From: =?UTF-8?q?Ji=C5=99=C3=AD=20=C5=BDupka?= To: autotest@test.kernel.org, kvm@vger.kernel.org, kvm-autotest@redhat.com, lmr@redhat.com, ldoktor@redhat.com, jzupka@redhat.com Subject: [virt][PATCH 2/3] virt: Adds functionality for vms. Date: Wed, 3 Oct 2012 14:10:34 +0200 Message-Id: <1349266235-12684-3-git-send-email-jzupka@redhat.com> In-Reply-To: <1349266235-12684-1-git-send-email-jzupka@redhat.com> References: <1349266235-12684-1-git-send-email-jzupka@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Allow creating of machine with tap devices which are not connected to bridge. Add function for fill virtnet object with address. Signed-off-by: Ji?í Župka --- virttest/kvm_vm.py | 9 +++-- virttest/utils_misc.py | 45 +++++++++++++++++------------ virttest/utils_misc_unittest.py | 59 +++++++++++++++++++++++++++++++++++++++ virttest/virt_vm.py | 20 +++++++++++++ 4 files changed, 110 insertions(+), 23 deletions(-) diff --git a/virttest/kvm_vm.py b/virttest/kvm_vm.py index 9877d55..7d4f93f 100644 --- a/virttest/kvm_vm.py +++ b/virttest/kvm_vm.py @@ -958,7 +958,7 @@ class VM(virt_vm.BaseVM): qemu_cmd += add_name(hlp, name) # no automagic devices please defaults = params.get("defaults", "no") - if has_option(hlp,"nodefaults") and defaults != "yes": + if has_option(hlp, "nodefaults") and defaults != "yes": qemu_cmd += " -nodefaults" # Add monitors for monitor_name in params.objects("monitors"): @@ -1074,7 +1074,7 @@ class VM(virt_vm.BaseVM): for nic in vm.virtnet: # setup nic parameters as needed - nic = vm.add_nic(**dict(nic)) # add_netdev if netdev_id not set + nic = vm.add_nic(**dict(nic)) # add_netdev if netdev_id not set # gather set values or None if unset vlan = int(nic.get('vlan')) netdev_id = nic.get('netdev_id') @@ -2073,7 +2073,7 @@ class VM(virt_vm.BaseVM): nic.set_if_none('nettype', 'bridge') if nic.nettype == 'bridge': # implies tap # destination is required, hard-code reasonable default if unset - nic.set_if_none('netdst', 'virbr0') + # nic.set_if_none('netdst', 'virbr0') # tapfd allocated/set in activate because requires system resources nic.set_if_none('tapfd_id', utils_misc.generate_random_id()) elif nic.nettype == 'user': @@ -2151,7 +2151,8 @@ class VM(virt_vm.BaseVM): error.context("Raising bridge for " + msg_sfx + attach_cmd, logging.debug) # assume this will puke if netdst unset - utils_misc.add_to_bridge(nic.ifname, nic.netdst) + if not nic.netdst is None: + utils_misc.add_to_bridge(nic.ifname, nic.netdst) elif nic.nettype == 'user': attach_cmd += " user,name=%s" % nic.ifname else: # unsupported nettype diff --git a/virttest/utils_misc.py b/virttest/utils_misc.py index f03e922..4376f44 100644 --- a/virttest/utils_misc.py +++ b/virttest/utils_misc.py @@ -62,7 +62,7 @@ class Bridge(object): """ br_i = re.compile("^(\S+).*?(\S+)$", re.MULTILINE) nbr_i = re.compile("^\s+(\S+)$", re.MULTILINE) - out_line = utils.run("brctl show", verbose=False).stdout.splitlines() + out_line = (utils.run("brctl show", verbose=False).stdout.splitlines()) result = dict() bridge = None iface = None @@ -226,7 +226,7 @@ class BRAddIfError(NetError): self.details = details def __str__(self): - return ("Can not add if %s to bridge %s: %s" % + return ("Can't remove interface %s from bridge %s: %s" % (self.ifname, self.brname, self.details)) @@ -249,7 +249,7 @@ class IfNotInBridgeError(NetError): self.details = details def __str__(self): - return ("If %s in any bridge: %s" % + return ("Interface %s is not present on any bridge: %s" % (self.ifname, self.details)) @@ -260,7 +260,7 @@ class BRNotExistError(NetError): self.details = details def __str__(self): - return ("Bridge %s not exists: %s" % (self.brname, self.details)) + return ("Bridge %s does not exist: %s" % (self.brname, self.details)) class IfChangeBrError(NetError): @@ -272,7 +272,7 @@ class IfChangeBrError(NetError): self.details = details def __str__(self): - return ("Can not change if %s from bridge %s to bridge %s: %s" % + return ("Can't move interface %s from bridge %s to bridge %s: %s" % (self.ifname, self.new_brname, self.oldbrname, self.details)) @@ -284,7 +284,7 @@ class IfChangeAddrError(NetError): self.details = details def __str__(self): - return ("Can not change if %s from bridge %s to bridge %s: %s" % + return ("Can't change interface IP address %s from interface %s: %s" % (self.ifname, self.ipaddr, self.details)) @@ -294,8 +294,9 @@ class BRIpError(NetError): self.brname = brname def __str__(self): - return ("Bridge %s doesn't have assigned any ip address. It is" - " impossible to start dnsmasq for this bridge." % (self.brname)) + return ("Bridge %s doesn't have an IP address assigned. It's" + " impossible to start dnsmasq for this bridge." % + (self.brname)) class HwAddrSetError(NetError): @@ -720,7 +721,8 @@ class VirtIface(PropCan): Networking information for single guest interface and host connection. """ - __slots__ = ['nic_name', 'mac', 'nic_model', 'ip', 'nettype', 'netdst'] + __slots__ = ['nic_name', 'g_nic_name', 'mac', 'nic_model', 'ip', + 'nettype', 'netdst'] # Make sure first byte generated is always zero and it follows # the class definition. This helps provide more predictable # addressing while avoiding clashes between multiple NICs. @@ -4049,7 +4051,7 @@ def local_runner_status(cmd, timeout=None): def get_net_if(runner=None): """ @param output: Output form ip link command. - @return: List of netowork interface + @return: List of network interfaces. """ if runner is None: runner = local_runner @@ -4060,8 +4062,8 @@ def get_net_if(runner=None): def get_net_if_addrs(if_name, runner=None): """ - Get network device ip addresses. ioctl not used because there is - incompatibility with ipv6. + Get network device ip addresses. ioctl not used because it's not + compatible with ipv6 address. @param if_name: Name of interface. @return: List ip addresses of network interface. @@ -4086,7 +4088,7 @@ def get_net_if_and_addrs(runner=None): return ret -def set_net_if_ip(if_name, ip_addr): +def set_net_if_ip(if_name, ip_addr, runner=None): """ Get network device ip addresses. ioctl not used because there is incompatibility with ipv6. @@ -4095,9 +4097,11 @@ def set_net_if_ip(if_name, ip_addr): @param ip_addr: Interface ip addr in format "ip_address/mask". @raise: IfChangeAddrError. """ + if runner is None: + runner = local_runner cmd = "ip addr add %s dev %s" % (ip_addr, if_name) try: - utils.run(cmd, verbose=False) + runner(cmd) except error.CmdError, e: raise IfChangeAddrError(if_name, ip_addr, e) @@ -4114,11 +4118,13 @@ def ipv6_from_mac_addr(mac_addr): def check_add_dnsmasq_to_br(br_name, tmpdir): """ Add dnsmasq for bridge. dnsmasq could be added only if bridge - have assigned ip address. + has assigned ip address. @param bridge_name: Name of bridge. @param bridge_ip: Bridge ip. @param tmpdir: Tmp dir for save pid file and ip range file. + @return: When new dnsmasq is started name of pidfile otherwise return + None because system dnsmasq is already started on bridge. """ br_ips = get_net_if_addrs(br_name)["ipv4"] if not br_ips: @@ -4144,7 +4150,8 @@ def check_add_dnsmasq_to_br(br_name, tmpdir): " --dhcp-lease-max=127 --dhcp-no-override" % (os.path.join(tmpdir, pidfile), br_ips[0], dhcp_ip_start, dhcp_ip_end, (os.path.join(tmpdir, leases)))) - return pidfile + return pidfile + return None @__init_openvswitch @@ -4152,7 +4159,7 @@ def find_bridge_manager(br_name, ovs=None): """ Finds bridge which contain interface iface_name. - @param iface_name: Name of interface. + @param br_name: Name of interface. @return: (br_manager) which contain bridge or None. """ if ovs is None: @@ -4169,7 +4176,7 @@ def find_bridge_manager(br_name, ovs=None): @__init_openvswitch def find_current_bridge(iface_name, ovs=None): """ - Finds bridge which contain interface iface_name. + Finds bridge which contains interface iface_name. @param iface_name: Name of interface. @return: (br_manager, Bridge) which contain iface_name or None. @@ -4192,7 +4199,7 @@ def find_current_bridge(iface_name, ovs=None): @__init_openvswitch def change_iface_bridge(ifname, new_bridge, ovs=None): """ - Change bridge on which is port added. + Change bridge on which interface was added. @param ifname: Iface name or Iface struct. @param new_bridge: Name of new bridge. diff --git a/virttest/utils_misc_unittest.py b/virttest/utils_misc_unittest.py index 6175041..3e701b2 100755 --- a/virttest/utils_misc_unittest.py +++ b/virttest/utils_misc_unittest.py @@ -126,6 +126,65 @@ node 0 raise ValueError("Could not locate locate '%s' on fake cmd db" % cmd) +class test_Bridge(unittest.TestCase): + class FakeCmd(object): + iter = 0 + + def __init__(self, *args, **kargs): + self.fake_cmds = [ +"""bridge name bridge id STP enabled interfaces +virbr0 8000.52540018638c yes virbr0-nic +virbr1 8000.525400c0b080 yes em1 + virbr1-nic +""", +"""bridge name bridge id STP enabled interfaces +""", +"""bridge name bridge id STP enabled interfaces +virbr0 8000.52540018638c yes virbr0-nic + virbr2-nic + virbr3-nic +virbr1 8000.525400c0b080 yes em1 + virbr1-nic + virbr4-nic + virbr5-nic +virbr2 8000.525400c0b080 yes em1 + virbr10-nic + virbr40-nic + virbr50-nic +"""] + + self.stdout = self.get_stdout() + self.__class__.iter += 1 + + def get_stdout(self): + return self.fake_cmds[self.__class__.iter] + + def setUp(self): + self.god = mock.mock_god(ut=self) + + def utils_run(*args, **kargs): + return test_Bridge.FakeCmd(*args, **kargs) + + self.god.stub_with(utils, 'run', utils_run) + + def test_getstructure(self): + + br = utils_misc.Bridge().get_structure() + self.assertEqual(br, {'virbr1': ['em1', 'virbr1-nic'], + 'virbr0': ['virbr0-nic']}) + + br = utils_misc.Bridge().get_structure() + self.assertEqual(br, {}) + + br = utils_misc.Bridge().get_structure() + self.assertEqual(br, {'virbr2': ['em1', 'virbr10-nic', + 'virbr40-nic', 'virbr50-nic'], + 'virbr1': ['em1', 'virbr1-nic', 'virbr4-nic', + 'virbr5-nic'], + 'virbr0': ['virbr0-nic', 'virbr2-nic', + 'virbr3-nic']}) + + def utils_run(cmd): return FakeCmd(cmd) diff --git a/virttest/virt_vm.py b/virttest/virt_vm.py index 79dd08b..ff6a0f7 100644 --- a/virttest/virt_vm.py +++ b/virttest/virt_vm.py @@ -518,6 +518,7 @@ class BaseVM(object): # Make sure the IP address is assigned to one or more macs # for this guest macs = self.virtnet.mac_list() + if not utils_misc.verify_ip_address_ownership(arp_ip, macs): raise VMAddressVerificationError(nic.mac, arp_ip) logging.debug('Found/Verified IP %s for VM %s NIC %s' % ( @@ -525,6 +526,25 @@ class BaseVM(object): return arp_ip + def fill_addrs(self, addrs): + """ + Fill VM's nic address to the virtnet structure based on VM's address + structure addrs. + + @param addrs: Dict of interfaces and address + {"if_name":{"mac":['addrs',], + "ipv4":['addrs',], + "ipv6":['addrs',]}, + ...} + """ + for virtnet in self.virtnet: + for iface_name, iface in addrs.iteritems(): + if virtnet.mac in iface["mac"]: + virtnet.ip = {"ipv4": iface["ipv4"], + "ipv6": iface["ipv6"]} + virtnet.g_nic_name = iface_name + + def get_port(self, port, nic_index=0): """ Return the port in host space corresponding to port in guest space.