ia64/xen-unstable

changeset 13182:362233086f66

New XendNetwork and XendPIF classes, for implementing the Xen-API network and
PIF classes.

By Alastair Tse <atse@xensource.com>.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Mon Dec 25 14:47:36 2006 +0000 (2006-12-25)
parents ae3f3dd40df4
children 4fbefd9cb85e
files tools/python/xen/xend/XendNetwork.py tools/python/xen/xend/XendPIF.py
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/python/xen/xend/XendNetwork.py	Mon Dec 25 14:47:36 2006 +0000
     1.3 @@ -0,0 +1,119 @@
     1.4 +#============================================================================
     1.5 +# This library is free software; you can redistribute it and/or
     1.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
     1.7 +# License as published by the Free Software Foundation.
     1.8 +#
     1.9 +# This library is distributed in the hope that it will be useful,
    1.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.12 +# Lesser General Public License for more details.
    1.13 +#
    1.14 +# You should have received a copy of the GNU Lesser General Public
    1.15 +# License along with this library; if not, write to the Free Software
    1.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.17 +#============================================================================
    1.18 +# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
    1.19 +# Copyright (c) 2006 Xensource Inc.
    1.20 +#============================================================================
    1.21 +
    1.22 +import os
    1.23 +import commands
    1.24 +import re
    1.25 +import struct
    1.26 +import socket
    1.27 +
    1.28 +from xen.xend.XendRoot import instance as xendroot
    1.29 +
    1.30 +IP_ROUTE_RE = r'^default via ([\d\.]+) dev (\w+)'
    1.31 +
    1.32 +def linux_get_default_network():
    1.33 +    """Returns the network details of the host."""
    1.34 +
    1.35 +    ip_cmd = '/sbin/ip route'
    1.36 +    rc, output = commands.getstatusoutput(ip_cmd)
    1.37 +    default_route = None
    1.38 +    default_dev = None
    1.39 +    default_netmask = None
    1.40 +    if rc == 0:
    1.41 +        # find default route/device
    1.42 +        for line in output.split('\n'):
    1.43 +            is_default = re.search(IP_ROUTE_RE, line)
    1.44 +            if is_default:
    1.45 +                default_route = is_default.group(1)
    1.46 +                default_dev = is_default.group(2)
    1.47 +
    1.48 +        # find network address and network mask
    1.49 +        if default_dev:
    1.50 +            dev_re = r'^([\d\.]+)/(\d+) dev %s' % default_dev
    1.51 +            for line in output.split('\n'):
    1.52 +                is_dev = re.search(dev_re, line)
    1.53 +                if is_dev:
    1.54 +                    # convert integer netmask to string representation
    1.55 +                    netmask = 0xffffffff ^ (2**(32-int(is_dev.group(2))) - 1)
    1.56 +                    packed = struct.pack('!I', netmask)
    1.57 +                    default_netmask = socket.inet_ntoa(packed)
    1.58 +
    1.59 +    return (default_route, default_netmask)
    1.60 +
    1.61 +
    1.62 +class XendNetwork:
    1.63 +    def __init__(self, uuid, name, description, gateway, netmask):
    1.64 +        self.uuid = uuid
    1.65 +        self.name_label = name 
    1.66 +        self.name_description = description
    1.67 +        self.default_gateway = gateway
    1.68 +        self.default_netmask = netmask
    1.69 +        self.vifs = {}
    1.70 +        self.pifs = {}
    1.71 +
    1.72 +    def get_name_label(self):
    1.73 +        return self.name_label
    1.74 +
    1.75 +    def set_name_label(self, new_name):
    1.76 +        self.name_label = new_name
    1.77 +
    1.78 +    def get_name_description(self):
    1.79 +        return self.name_description
    1.80 +
    1.81 +    def set_name_description(self, new_desc):
    1.82 +        self.name_description = new_desc
    1.83 +
    1.84 +    def get_default_gateway(self):
    1.85 +        return self.default_gateway
    1.86 +
    1.87 +    def set_default_gateway(self, new_gateway):
    1.88 +        if re.search('^\d+\.\d+\.\d+\.\d+$', new_gateway):
    1.89 +            self.default_gateway = new_gateway
    1.90 +
    1.91 +    def get_default_netmask(self):
    1.92 +        return self.default_netmask
    1.93 +
    1.94 +    def set_default_netmask(self, new_netmask):
    1.95 +        if re.search('^\d+\.\d+\.\d+\.\d+$', new_netmask):
    1.96 +            self.default_netmask = new_netmask
    1.97 +
    1.98 +    def add_pif(self, pif):
    1.99 +        self.pifs[pif.get_uuid()] = pif
   1.100 +
   1.101 +    def remove_pif(self, pif_uuid):
   1.102 +        if pif_uuid in self.pifs:
   1.103 +            del self.pifs[pif_uuid]
   1.104 +
   1.105 +    def add_vif(self, vif):
   1.106 +        self.vifs[vif.get_uuid()] = vif
   1.107 +
   1.108 +    def remove_vif(self, vif_uuid):
   1.109 +        if vif_uuid in self.vifs:
   1.110 +            del self.vifs[vif_uuid]
   1.111 +        
   1.112 +    def get_record(self):
   1.113 +        return {
   1.114 +            'uuid': self.uuid,
   1.115 +            'name_label': self.name_label,
   1.116 +            'name_description': self.name_description,
   1.117 +            'default_gateway': self.default_gateway,
   1.118 +            'default_netmask': self.default_netmask,
   1.119 +            'VIFs': self.vifs.keys(),
   1.120 +            'PIFs': self.pifs.keys()
   1.121 +        }
   1.122 +           
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/python/xen/xend/XendPIF.py	Mon Dec 25 14:47:36 2006 +0000
     2.3 @@ -0,0 +1,157 @@
     2.4 +#============================================================================
     2.5 +# This library is free software; you can redistribute it and/or
     2.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
     2.7 +# License as published by the Free Software Foundation.
     2.8 +#
     2.9 +# This library is distributed in the hope that it will be useful,
    2.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    2.12 +# Lesser General Public License for more details.
    2.13 +#
    2.14 +# You should have received a copy of the GNU Lesser General Public
    2.15 +# License along with this library; if not, write to the Free Software
    2.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2.17 +#============================================================================
    2.18 +# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
    2.19 +# Copyright (c) 2006 Xensource Inc.
    2.20 +#============================================================================
    2.21 +
    2.22 +import os
    2.23 +import commands
    2.24 +import re
    2.25 +import socket
    2.26 +
    2.27 +from xen.xend.XendRoot import instance as xendroot
    2.28 +from xen.xend.XendLogging import log
    2.29 +
    2.30 +MAC_RE = ':'.join(['[0-9a-f]{2}'] * 6)
    2.31 +IP_IFACE_RE = r'^\d+: (\w+):.*mtu (\d+) .* link/\w+ ([0-9a-f:]+)'
    2.32 +
    2.33 +def linux_phy_to_virt(pif_name):
    2.34 +    return 'eth' + re.sub(r'^[a-z]+', '', pif_name)
    2.35 +
    2.36 +def linux_get_phy_ifaces():
    2.37 +    """Returns a list of physical interfaces.
    2.38 +
    2.39 +    Identifies PIFs as those that have a interface name starting with 'p'
    2.40 +    and have the fake 'fe:ff:ff:ff:ff:ff' MAC address.
    2.41 +
    2.42 +    See /etc/xen/scripts/network-bridge for how the devices are renamed.
    2.43 +
    2.44 +    @rtype: array of 3-element tuple (name, mtu, mac)
    2.45 +    """
    2.46 +    
    2.47 +    ip_cmd = '/sbin/ip -o link show'
    2.48 +    rc, output = commands.getstatusoutput(ip_cmd)
    2.49 +    ifaces = {}
    2.50 +    phy_ifaces = []
    2.51 +    if rc == 0:
    2.52 +        # parse all interfaces into (name, mtu, mac)
    2.53 +        for line in output.split('\n'):
    2.54 +            has_if = re.search(IP_IFACE_RE, line)
    2.55 +            if has_if:
    2.56 +                ifaces[has_if.group(1)] = has_if.groups()
    2.57 +                
    2.58 +        # resolve pifs' mac addresses
    2.59 +        for name, mtu, mac in ifaces.values():
    2.60 +            if name[0] == 'p' and mac == 'fe:ff:ff:ff:ff:ff':
    2.61 +                bridged_ifname = linux_phy_to_virt(name)
    2.62 +                bridged_if = ifaces.get(bridged_ifname)
    2.63 +                if bridged_if:
    2.64 +                    bridged_mac = bridged_if[2]
    2.65 +                phy_ifaces.append((name, int(mtu), bridged_mac))
    2.66 +                
    2.67 +    return phy_ifaces
    2.68 +
    2.69 +def linux_set_mac(iface, mac):
    2.70 +    if not re.search(MAC_RE, mac):
    2.71 +        return False
    2.72 +
    2.73 +    ip_mac_cmd = '/sbin/ip link set %s addr %s' % \
    2.74 +                 (linux_phy_to_virt(iface), mac)
    2.75 +    rc, output = commands.getstatusoutput(ip_mac_cmd)
    2.76 +    if rc == 0:
    2.77 +        return True
    2.78 +
    2.79 +    return False
    2.80 +
    2.81 +def linux_set_mtu(iface, mtu):
    2.82 +    try:
    2.83 +        ip_mtu_cmd = '/sbin/ip link set %s mtu %d' % \
    2.84 +                     (linux_phy_to_virt(iface), int(mtu))
    2.85 +        rc, output = commands.getstatusoutput(ip_mtu_cmd)
    2.86 +        if rc == 0:
    2.87 +            return True
    2.88 +        return False
    2.89 +    except ValueError:
    2.90 +        return False
    2.91 +
    2.92 +def same_dir_rename(old_path, new_path):
    2.93 +    """Ensure that the old_path and new_path refer to files in the same
    2.94 +    directory."""
    2.95 +    old_abs = os.path.normpath(old_path)
    2.96 +    new_abs = os.path.normpath(new_path)
    2.97 +    if os.path.dirname(old_abs) == os.path.dirname(new_abs):
    2.98 +        os.rename(old_abs, new_abs)
    2.99 +    else:
   2.100 +        log.warning("Unable to ensure name is new name is safe: %s" % new_abs)
   2.101 +    
   2.102 +
   2.103 +class XendPIF:
   2.104 +    """Representation of a Physical Network Interface."""
   2.105 +    
   2.106 +    def __init__(self, uuid, name, mtu, mac):
   2.107 +        self.uuid = uuid
   2.108 +        self.name = name
   2.109 +        self.mac = mac
   2.110 +        self.mtu = mtu
   2.111 +        self.vlan = ''
   2.112 +        self.network = None
   2.113 +
   2.114 +    def set_name(self, new_name):
   2.115 +        self.name = new_name
   2.116 +            
   2.117 +    def get_name(self):
   2.118 +        return self.name
   2.119 +
   2.120 +    def get_uuid(self):
   2.121 +        return self.uuid
   2.122 +
   2.123 +    def get_mac(self):
   2.124 +        return self.mac
   2.125 +
   2.126 +    def get_vlan(self):
   2.127 +        return self.vlan
   2.128 +
   2.129 +    def set_mac(self, new_mac):
   2.130 +        success = linux_set_mac(new_mac)
   2.131 +        if success:
   2.132 +            self.mac = new_mac
   2.133 +        return success
   2.134 +
   2.135 +    def set_mtu(self, new_mtu):
   2.136 +        success = linux_set_mtu(new_mtu)
   2.137 +        if success:
   2.138 +            self.mtu = new_mtu
   2.139 +        return success
   2.140 +
   2.141 +    def get_io_read_kbs(self):
   2.142 +        return 0.0
   2.143 +
   2.144 +    def get_io_write_kbs(self):
   2.145 +        return 0.0
   2.146 +
   2.147 +    def get_record(self):
   2.148 +        if self.network:
   2.149 +            network_uuid = self.network.get_uuid()
   2.150 +        else:
   2.151 +            network_uuid = None
   2.152 +
   2.153 +        return {'name': self.name,
   2.154 +                'MAC': self.mac,
   2.155 +                'MTU': self.mtu,
   2.156 +                'VLAN': self.vlan,
   2.157 +                'network': network_uuid,
   2.158 +                'io_read_kbs': self.get_io_read_kbs(),
   2.159 +                'io_write_kbs': self.get_io_write_kbs()}
   2.160 +