diff mbox

[virt,2/3] virt: Adds functionality for vms.

Message ID 1349266235-12684-3-git-send-email-jzupka@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jiri Zupka Oct. 3, 2012, 12:10 p.m. UTC
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 <jzupka@redhat.com>
---
 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 mbox

Patch

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.