From patchwork Sun Aug 2 23:58:10 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Goldish X-Patchwork-Id: 38807 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n72Nskq1009541 for ; Sun, 2 Aug 2009 23:54:46 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753866AbZHBXym (ORCPT ); Sun, 2 Aug 2009 19:54:42 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753860AbZHBXyl (ORCPT ); Sun, 2 Aug 2009 19:54:41 -0400 Received: from mx2.redhat.com ([66.187.237.31]:37200 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753706AbZHBXyi (ORCPT ); Sun, 2 Aug 2009 19:54:38 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n72NrsA7016610; Sun, 2 Aug 2009 19:54:04 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n72Nrhoj022140; Sun, 2 Aug 2009 19:53:43 -0400 Received: from localhost.localdomain (dhcp-1-188.tlv.redhat.com [10.35.1.188]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n72Nre6H017975; Sun, 2 Aug 2009 19:53:42 -0400 From: Michael Goldish To: autotest@test.kernel.org, kvm@vger.kernel.org Cc: Michael Goldish Subject: [KVM-AUTOTEST PATCH 01/12] KVM test: add some MAC/IP address utilities to kvm_utils Date: Mon, 3 Aug 2009 02:58:10 +0300 Message-Id: <7845d2fd228ec0232af10e48dbb29e1076a265d6.1249257056.git.mgoldish@redhat.com> In-Reply-To: <1249257501-19337-1-git-send-email-mgoldish@redhat.com> References: <1249257501-19337-1-git-send-email-mgoldish@redhat.com> X-Scanned-By: MIMEDefang 2.58 on 172.16.27.26 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org 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 ' 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 --- client/tests/kvm/kvm_utils.py | 110 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 108 insertions(+), 2 deletions(-) diff --git a/client/tests/kvm/kvm_utils.py b/client/tests/kvm/kvm_utils.py index e897e78..5d8291f 100644 --- a/client/tests/kvm/kvm_utils.py +++ b/client/tests/kvm/kvm_utils.py @@ -1,7 +1,7 @@ import md5, thread, subprocess, time, string, random, socket, os, signal, pty import select, re, logging -from autotest_lib.client.bin import utils -from autotest_lib.client.common_lib import error +#from autotest_lib.client.bin import utils +#from autotest_lib.client.common_lib import error import kvm_subprocess """ @@ -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):