diff mbox

[KVM-AUTOTEST,01/12] KVM test: add some MAC/IP address utilities to kvm_utils

Message ID a3af95f9d9917df116f4df6d18fcbf57a7a87fca.1249582934.git.mgoldish@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Michael Goldish Aug. 6, 2009, 6:41 p.m. UTC
Add function get_mac_ip_pair_from_dict() which gets a dict (specified in the
config file by the user) and fetches a MAC-IP address pair according to a
certain syntax.  The syntax allows the user to specify a group of MAC-IP
address ranges.  For example:

address_ranges = r1 r2 r3

address_range_base_mac_r1 = 55:44:33:22:11:00
address_range_base_ip_r1 = 10.0.0.0
address_range_size_r1 = 16

address_range_base_mac_r2 = 55:44:33:22:11:40
address_range_base_ip_r2 = 10.0.0.60
address_range_size_r2 = 25

address_range_base_mac_r3 = 55:44:33:22:12:10
address_range_base_ip_r3 = 10.0.1.20
address_range_size_r3 = 230

The lines above may be specified globally, so that they apply to all VMs and
all NICs.

However, a line similar to the following must be specified per NIC (each VM may
have several NICs):

address_index = 0

Currently, we usually use a single VM and a single NIC, so specifying
address_index once should suffice.  If a test requires an additional NIC the
user should add something like:

address_index_nic2 = 1

The index is simply the index in the MAC-IP table that consists of all the
specified ranges.  In the above example, if the user specifies an index of 18,
the MAC-IP pair will be taken from the second range, because the first range
has only 16 entries.

When running migration, both the source and destination VMs should have the
same address_index, because they should have the same MAC and IP addresses.

Note that different copies of the KVM test, running simultaneously in the same
network environment, _must_ specify different MAC-IP pools.  This can be done
in several ways:
- By specifying the ranges (as in the example above) in an external file such
as /etc/kvm-autotest/client_mac_ip_pool.cfg, and setting up that file for each
host manually
- By keeping several .cfg files with different names that match the hostname
of each host, e.g. mac_ip_pool_hostname1.cfg, mac_ip_pool_hostname2.cfg
(hostname1 and hostname2 should be replaced by actual hostnames), and parsing
the right file in the control file at runtime
- By defining all the different pools in a variants block in a single file,
and specifying 'only <hostname>' at runtime in the control file (using
config.parse_string())
When we start running in server mode, assigning MAC and IP addresses to hosts
can be done automatically by the server, but the user will still be required to
specify a single global pool for the server (which the server will divide among
the hosts).  The address_index parameter will be specified inside the regular
config file, and does not need to be different for each host.

This patch also adds some small utility functions used by
get_mac_ip_pair_from_dict().

Signed-off-by: Michael Goldish <mgoldish@redhat.com>
---
 client/tests/kvm/kvm_utils.py |  106 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 106 insertions(+), 0 deletions(-)
diff mbox

Patch

diff --git a/client/tests/kvm/kvm_utils.py b/client/tests/kvm/kvm_utils.py
index e897e78..4891592 100644
--- a/client/tests/kvm/kvm_utils.py
+++ b/client/tests/kvm/kvm_utils.py
@@ -46,6 +46,112 @@  def get_sub_dict_names(dict, keyword):
         return []
 
 
+# Functions related to MAC/IP addresses
+
+def mac_str_to_int(addr):
+    """
+    Convert MAC address string to integer.
+
+    @param addr: String representing the MAC address.
+    """
+    return sum(int(s, 16) * 256 ** i
+               for i, s in enumerate(reversed(addr.split(":"))))
+
+
+def mac_int_to_str(addr):
+    """
+    Convert MAC address integer to string.
+
+    @param addr: Integer representing the MAC address.
+    """
+    return ":".join("%02x" % (addr >> 8 * i & 0xFF)
+                    for i in reversed(range(6)))
+
+
+def ip_str_to_int(addr):
+    """
+    Convert IP address string to integer.
+
+    @param addr: String representing the IP address.
+    """
+    return sum(int(s) * 256 ** i
+               for i, s in enumerate(reversed(addr.split("."))))
+
+
+def ip_int_to_str(addr):
+    """
+    Convert IP address integer to string.
+
+    @param addr: Integer representing the IP address.
+    """
+    return ".".join(str(addr >> 8 * i & 0xFF)
+                    for i in reversed(range(4)))
+
+
+def offset_mac(base, offset):
+    """
+    Add offset to a given MAC address.
+
+    @param base: String representing a MAC address.
+    @param offset: Offset to add to base (integer)
+    @return: A string representing the offset MAC address.
+    """
+    return mac_int_to_str(mac_str_to_int(base) + offset)
+
+
+def offset_ip(base, offset):
+    """
+    Add offset to a given IP address.
+
+    @param base: String representing an IP address.
+    @param offset: Offset to add to base (integer)
+    @return: A string representing the offset IP address.
+    """
+    return ip_int_to_str(ip_str_to_int(base) + offset)
+
+
+def get_mac_ip_pair_from_dict(dict):
+    """
+    Fetch a MAC-IP address pair from dict and return it.
+
+    The parameters in dict are expected to conform to a certain syntax.
+    Typical usage may be:
+
+    address_ranges = r1 r2 r3
+
+    address_range_base_mac_r1 = 55:44:33:22:11:00
+    address_range_base_ip_r1 = 10.0.0.0
+    address_range_size_r1 = 16
+
+    address_range_base_mac_r2 = 55:44:33:22:11:40
+    address_range_base_ip_r2 = 10.0.0.60
+    address_range_size_r2 = 25
+
+    address_range_base_mac_r3 = 55:44:33:22:12:10
+    address_range_base_ip_r3 = 10.0.1.20
+    address_range_size_r3 = 230
+
+    address_index = 0
+
+    All parameters except address_index specify a MAC-IP address pool.  The
+    pool consists of several MAC-IP address ranges.
+    address_index specified the index of the desired MAC-IP pair from the pool.
+
+    @param dict: The dictionary from which to fetch the addresses.
+    """
+    index = int(dict.get("address_index", 0))
+    for mac_range_name in get_sub_dict_names(dict, "address_ranges"):
+        mac_range_params = get_sub_dict(dict, mac_range_name)
+        mac_base = mac_range_params.get("address_range_base_mac")
+        ip_base = mac_range_params.get("address_range_base_ip")
+        size = int(mac_range_params.get("address_range_size", 1))
+        if index < size:
+            return (mac_base and offset_mac(mac_base, index),
+                    ip_base and offset_ip(ip_base, index))
+        index -= size
+    return (None, None)
+
+
 # Functions for working with the environment (a dict-like object)
 
 def is_vm(obj):