mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
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>
This commit is contained in:
1 parent
3e9ef3ef0a
commit
d9510a25ab
2 files changed
+276
No files matched your search
@@ -0,0 +1,119 @@
|
||||
#============================================================================
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
|
||||
# Copyright (c) 2006 Xensource Inc.
|
||||
#============================================================================
|
||||
|
||||
import os
|
||||
import commands
|
||||
import re
|
||||
import struct
|
||||
import socket
|
||||
|
||||
from xen.xend.XendRoot import instance as xendroot
|
||||
|
||||
IP_ROUTE_RE = r'^default via ([\d\.]+) dev (\w+)'
|
||||
|
||||
def linux_get_default_network():
|
||||
"""Returns the network details of the host."""
|
||||
|
||||
ip_cmd = '/sbin/ip route'
|
||||
rc, output = commands.getstatusoutput(ip_cmd)
|
||||
default_route = None
|
||||
default_dev = None
|
||||
default_netmask = None
|
||||
if rc == 0:
|
||||
# find default route/device
|
||||
for line in output.split('\n'):
|
||||
is_default = re.search(IP_ROUTE_RE, line)
|
||||
if is_default:
|
||||
default_route = is_default.group(1)
|
||||
default_dev = is_default.group(2)
|
||||
|
||||
# find network address and network mask
|
||||
if default_dev:
|
||||
dev_re = r'^([\d\.]+)/(\d+) dev %s' % default_dev
|
||||
for line in output.split('\n'):
|
||||
is_dev = re.search(dev_re, line)
|
||||
if is_dev:
|
||||
# convert integer netmask to string representation
|
||||
netmask = 0xffffffff ^ (2**(32-int(is_dev.group(2))) - 1)
|
||||
packed = struct.pack('!I', netmask)
|
||||
default_netmask = socket.inet_ntoa(packed)
|
||||
|
||||
return (default_route, default_netmask)
|
||||
|
||||
|
||||
class XendNetwork:
|
||||
def __init__(self, uuid, name, description, gateway, netmask):
|
||||
self.uuid = uuid
|
||||
self.name_label = name
|
||||
self.name_description = description
|
||||
self.default_gateway = gateway
|
||||
self.default_netmask = netmask
|
||||
self.vifs = {}
|
||||
self.pifs = {}
|
||||
|
||||
def get_name_label(self):
|
||||
return self.name_label
|
||||
|
||||
def set_name_label(self, new_name):
|
||||
self.name_label = new_name
|
||||
|
||||
def get_name_description(self):
|
||||
return self.name_description
|
||||
|
||||
def set_name_description(self, new_desc):
|
||||
self.name_description = new_desc
|
||||
|
||||
def get_default_gateway(self):
|
||||
return self.default_gateway
|
||||
|
||||
def set_default_gateway(self, new_gateway):
|
||||
if re.search('^\d+\.\d+\.\d+\.\d+$', new_gateway):
|
||||
self.default_gateway = new_gateway
|
||||
|
||||
def get_default_netmask(self):
|
||||
return self.default_netmask
|
||||
|
||||
def set_default_netmask(self, new_netmask):
|
||||
if re.search('^\d+\.\d+\.\d+\.\d+$', new_netmask):
|
||||
self.default_netmask = new_netmask
|
||||
|
||||
def add_pif(self, pif):
|
||||
self.pifs[pif.get_uuid()] = pif
|
||||
|
||||
def remove_pif(self, pif_uuid):
|
||||
if pif_uuid in self.pifs:
|
||||
del self.pifs[pif_uuid]
|
||||
|
||||
def add_vif(self, vif):
|
||||
self.vifs[vif.get_uuid()] = vif
|
||||
|
||||
def remove_vif(self, vif_uuid):
|
||||
if vif_uuid in self.vifs:
|
||||
del self.vifs[vif_uuid]
|
||||
|
||||
def get_record(self):
|
||||
return {
|
||||
'uuid': self.uuid,
|
||||
'name_label': self.name_label,
|
||||
'name_description': self.name_description,
|
||||
'default_gateway': self.default_gateway,
|
||||
'default_netmask': self.default_netmask,
|
||||
'VIFs': self.vifs.keys(),
|
||||
'PIFs': self.pifs.keys()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
#============================================================================
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
|
||||
# Copyright (c) 2006 Xensource Inc.
|
||||
#============================================================================
|
||||
|
||||
import os
|
||||
import commands
|
||||
import re
|
||||
import socket
|
||||
|
||||
from xen.xend.XendRoot import instance as xendroot
|
||||
from xen.xend.XendLogging import log
|
||||
|
||||
MAC_RE = ':'.join(['[0-9a-f]{2}'] * 6)
|
||||
IP_IFACE_RE = r'^\d+: (\w+):.*mtu (\d+) .* link/\w+ ([0-9a-f:]+)'
|
||||
|
||||
def linux_phy_to_virt(pif_name):
|
||||
return 'eth' + re.sub(r'^[a-z]+', '', pif_name)
|
||||
|
||||
def linux_get_phy_ifaces():
|
||||
"""Returns a list of physical interfaces.
|
||||
|
||||
Identifies PIFs as those that have a interface name starting with 'p'
|
||||
and have the fake 'fe:ff:ff:ff:ff:ff' MAC address.
|
||||
|
||||
See /etc/xen/scripts/network-bridge for how the devices are renamed.
|
||||
|
||||
@rtype: array of 3-element tuple (name, mtu, mac)
|
||||
"""
|
||||
|
||||
ip_cmd = '/sbin/ip -o link show'
|
||||
rc, output = commands.getstatusoutput(ip_cmd)
|
||||
ifaces = {}
|
||||
phy_ifaces = []
|
||||
if rc == 0:
|
||||
# parse all interfaces into (name, mtu, mac)
|
||||
for line in output.split('\n'):
|
||||
has_if = re.search(IP_IFACE_RE, line)
|
||||
if has_if:
|
||||
ifaces[has_if.group(1)] = has_if.groups()
|
||||
|
||||
# resolve pifs' mac addresses
|
||||
for name, mtu, mac in ifaces.values():
|
||||
if name[0] == 'p' and mac == 'fe:ff:ff:ff:ff:ff':
|
||||
bridged_ifname = linux_phy_to_virt(name)
|
||||
bridged_if = ifaces.get(bridged_ifname)
|
||||
if bridged_if:
|
||||
bridged_mac = bridged_if[2]
|
||||
phy_ifaces.append((name, int(mtu), bridged_mac))
|
||||
|
||||
return phy_ifaces
|
||||
|
||||
def linux_set_mac(iface, mac):
|
||||
if not re.search(MAC_RE, mac):
|
||||
return False
|
||||
|
||||
ip_mac_cmd = '/sbin/ip link set %s addr %s' % \
|
||||
(linux_phy_to_virt(iface), mac)
|
||||
rc, output = commands.getstatusoutput(ip_mac_cmd)
|
||||
if rc == 0:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def linux_set_mtu(iface, mtu):
|
||||
try:
|
||||
ip_mtu_cmd = '/sbin/ip link set %s mtu %d' % \
|
||||
(linux_phy_to_virt(iface), int(mtu))
|
||||
rc, output = commands.getstatusoutput(ip_mtu_cmd)
|
||||
if rc == 0:
|
||||
return True
|
||||
return False
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
def same_dir_rename(old_path, new_path):
|
||||
"""Ensure that the old_path and new_path refer to files in the same
|
||||
directory."""
|
||||
old_abs = os.path.normpath(old_path)
|
||||
new_abs = os.path.normpath(new_path)
|
||||
if os.path.dirname(old_abs) == os.path.dirname(new_abs):
|
||||
os.rename(old_abs, new_abs)
|
||||
else:
|
||||
log.warning("Unable to ensure name is new name is safe: %s" % new_abs)
|
||||
|
||||
|
||||
class XendPIF:
|
||||
"""Representation of a Physical Network Interface."""
|
||||
|
||||
def __init__(self, uuid, name, mtu, mac):
|
||||
self.uuid = uuid
|
||||
self.name = name
|
||||
self.mac = mac
|
||||
self.mtu = mtu
|
||||
self.vlan = ''
|
||||
self.network = None
|
||||
|
||||
def set_name(self, new_name):
|
||||
self.name = new_name
|
||||
|
||||
def get_name(self):
|
||||
return self.name
|
||||
|
||||
def get_uuid(self):
|
||||
return self.uuid
|
||||
|
||||
def get_mac(self):
|
||||
return self.mac
|
||||
|
||||
def get_vlan(self):
|
||||
return self.vlan
|
||||
|
||||
def set_mac(self, new_mac):
|
||||
success = linux_set_mac(new_mac)
|
||||
if success:
|
||||
self.mac = new_mac
|
||||
return success
|
||||
|
||||
def set_mtu(self, new_mtu):
|
||||
success = linux_set_mtu(new_mtu)
|
||||
if success:
|
||||
self.mtu = new_mtu
|
||||
return success
|
||||
|
||||
def get_io_read_kbs(self):
|
||||
return 0.0
|
||||
|
||||
def get_io_write_kbs(self):
|
||||
return 0.0
|
||||
|
||||
def get_record(self):
|
||||
if self.network:
|
||||
network_uuid = self.network.get_uuid()
|
||||
else:
|
||||
network_uuid = None
|
||||
|
||||
return {'name': self.name,
|
||||
'MAC': self.mac,
|
||||
'MTU': self.mtu,
|
||||
'VLAN': self.vlan,
|
||||
'network': network_uuid,
|
||||
'io_read_kbs': self.get_io_read_kbs(),
|
||||
'io_write_kbs': self.get_io_write_kbs()}
|
||||
|
||||