# HG changeset patch
# User Ewan Mellor <ewan@xxxxxxxxxxxxx>
# Date 1167234176 0
# Node ID a8e853aecb3ef24b7a77bb9022f475bfee564c37
# Parent 069d1364af539b78d89cbeaa7c898c0cda3ed0af
Added network.{create,destroy}, and PIF.{create,create_VLAN,destroy}, and
a first blush at support for VLANs through Xen-API.
Signed-off-by: Ewan Mellor <ewan@xxxxxxxxxxxxx>
---
tools/python/xen/xend/XendAPI.py | 58 ++++++++++++++----
tools/python/xen/xend/XendNode.py | 92 +++++++++++++++++++++-------
tools/python/xen/xend/XendPIF.py | 96 +++++++++++++++++++++++-------
tools/python/xen/xend/server/SrvServer.py | 4 -
4 files changed, 193 insertions(+), 57 deletions(-)
diff -r 069d1364af53 -r a8e853aecb3e tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py Wed Dec 27 15:39:32 2006 +0000
+++ b/tools/python/xen/xend/XendAPI.py Wed Dec 27 15:42:56 2006 +0000
@@ -469,13 +469,23 @@ class XendAPI:
'default_gateway',
'default_netmask']
+ def network_create(self, _, name_label, name_description,
+ default_gateway, default_netmask):
+ return xen_api_success(
+ XendNode.instance().network_create(name_label, name_description,
+ default_gateway,
+ default_netmask))
+
+ def network_destroy(self, _, ref):
+ return xen_api_success(XendNode.instance().network_destroy(ref))
+
def _get_network(self, ref):
return XendNode.instance().get_network(ref)
- def network_get_all(self, session):
+ def network_get_all(self, _):
return xen_api_success(XendNode.instance().get_network_refs())
- def network_get_record(self, session, ref):
+ def network_get_record(self, _, ref):
return xen_api_success(
XendNode.instance().get_network(ref).get_record())
@@ -524,8 +534,25 @@ class XendAPI:
PIF_attr_inst = PIF_attr_rw
+ PIF_methods = ['create_VLAN']
+
def _get_PIF(self, ref):
return XendNode.instance().pifs[ref]
+
+ def PIF_create(self, _, name, network_uuid, host_uuid, mac, mtu, vlan):
+ node = XendNode.instance()
+ if host_uuid != node.uuid:
+ return xen_api_error([HOST_HANDLE_INVALID, host_uuid])
+
+ elif _is_valid_ref(network_uuid, node.is_valid_network):
+ network = node.get_network(network_uuid)
+ return xen_api_success(node.PIF_create(name, mtu, vlan, mac,
+ network))
+ else:
+ return xen_api_error([NETWORK_HANDLE_INVALID, network_uuid])
+
+ def PIF_destroy(self, _, ref):
+ return xen_api_success(XendNode.instance().PIF_destroy(ref))
# object methods
def PIF_get_record(self, _, ref):
@@ -534,38 +561,45 @@ class XendAPI:
def PIF_get_all(self, _):
return xen_api_success(XendNode.instance().pifs.keys())
- def PIF_get_name(self, session, ref):
+ def PIF_get_name(self, _, ref):
return xen_api_success(self._get_PIF(ref).name)
- def PIF_get_network(self, session, ref):
+ def PIF_get_network(self, _, ref):
return xen_api_success(self._get_PIF(ref).network.uuid)
- def PIF_get_host(self, session, ref):
+ def PIF_get_host(self, _, ref):
return xen_api_success(self._get_PIF(ref).host.uuid)
- def PIF_get_MAC(self, session, ref):
+ def PIF_get_MAC(self, _, ref):
return xen_api_success(self._get_PIF(ref).mac)
- def PIF_get_MTU(self, session, ref):
+ def PIF_get_MTU(self, _, ref):
return xen_api_success(self._get_PIF(ref).mtu)
- def PIF_get_VLAN(self, session, ref):
+ def PIF_get_VLAN(self, _, ref):
return xen_api_success(self._get_PIF(ref).vlan)
- def PIF_get_io_read_kbs(self, session, ref):
+ def PIF_get_io_read_kbs(self, _, ref):
return xen_api_success(self._get_PIF(ref).get_io_read_kbs())
- def PIF_get_io_write_kbs(self, session, ref):
+ def PIF_get_io_write_kbs(self, _, ref):
return xen_api_success(self._get_PIF(ref).get_io_write_kbs())
def PIF_set_name(self, _, ref, name):
return xen_api_success(self._get_PIF(ref).set_name(name))
- def PIF_set_MAC(self, session, ref, mac):
+ def PIF_set_MAC(self, _, ref, mac):
return xen_api_success(self._get_PIF(ref).set_mac(name))
- def PIF_set_MTU(self, session, ref, mtu):
+ def PIF_set_MTU(self, _, ref, mtu):
return xen_api_success(self._get_PIF(ref).set_mtu(name))
+
+ def PIF_create_VLAN(self, _, ref, network, vlan):
+ if _is_valid_ref(network, XendNode.instance().is_valid_network):
+ return xen_api_success(XendNode.instance().PIF_create_VLAN(
+ ref, network, vlan))
+ else:
+ return xen_api_error([NETWORK_HANDLE_INVALID, network_uuid])
# Xen API: Class VM
diff -r 069d1364af53 -r a8e853aecb3e tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Wed Dec 27 15:39:32 2006 +0000
+++ b/tools/python/xen/xend/XendNode.py Wed Dec 27 15:42:56 2006 +0000
@@ -19,6 +19,9 @@ import os
import os
import socket
import xen.lowlevel.xc
+
+from xen.util import Brctl
+
from xen.xend import uuid
from xen.xend.XendError import XendError
from xen.xend.XendRoot import instance as xendroot
@@ -87,16 +90,14 @@ class XendNode:
saved_networks = self.state_store.load_state('network')
if saved_networks:
for net_uuid, network in saved_networks.items():
- self.networks[net_uuid] = XendNetwork(net_uuid,
- network.get('name_label'),
- network.get('name_description', ''),
- network.get('default_gateway', ''),
- network.get('default_netmask', ''))
+ self.network_create(network.get('name_label'),
+ network.get('name_description', ''),
+ network.get('default_gateway', ''),
+ network.get('default_netmask', ''),
+ False, net_uuid)
else:
gateway, netmask = linux_get_default_network()
- net_uuid = uuid.createString()
- net = XendNetwork(net_uuid, 'net0', '', gateway, netmask)
- self.networks[net_uuid] = net
+ self.network_create('net0', '', gateway, netmask, False)
# initialise PIFs
saved_pifs = self.state_store.load_state('pif')
@@ -104,19 +105,12 @@ class XendNode:
for pif_uuid, pif in saved_pifs.items():
if pif['network'] in self.networks:
network = self.networks[pif['network']]
- self.pifs[pif_uuid] = XendPIF(pif_uuid,
- pif['name'],
- pif['MTU'],
- pif['VLAN'],
- pif['MAC'],
- network,
- self)
+ self.PIF_create(pif['name'], pif['MTU'], pif['VLAN'],
+ pif['MAC'], network, False, pif_uuid)
else:
for name, mtu, mac in linux_get_phy_ifaces():
network = self.networks.values()[0]
- pif_uuid = uuid.createString()
- pif = XendPIF(pif_uuid, name, mtu, '', mac, network, self)
- self.pifs[pif_uuid] = pif
+ self.PIF_create(name, mtu, '', mac, network, False)
# initialise storage
saved_sr = self.state_store.load_state('sr')
@@ -126,6 +120,49 @@ class XendNode:
else:
sr_uuid = uuid.createString()
self.sr = XendStorageRepository(sr_uuid)
+
+
+ def network_create(self, name_label, name_description,
+ default_gateway, default_netmask, persist = True,
+ net_uuid = None):
+ if net_uuid is None:
+ net_uuid = uuid.createString()
+ self.networks[net_uuid] = XendNetwork(net_uuid, name_label,
+ name_description,
+ default_gateway,
+ default_netmask)
+ if persist:
+ self.save_networks()
+ return net_uuid
+
+
+ def network_destroy(self, net_uuid):
+ del self.networks[net_uuid]
+ self.save_networks()
+
+
+ def PIF_create(self, name, mtu, vlan, mac, network, persist = True,
+ pif_uuid = None):
+ if pif_uuid is None:
+ pif_uuid = uuid.createString()
+ self.pifs[pif_uuid] = XendPIF(pif_uuid, name, mtu, vlan, mac, network,
+ self)
+ if persist:
+ self.save_PIFs()
+ self.refreshBridges()
+ return pif_uuid
+
+
+ def PIF_create_VLAN(self, pif_uuid, network_uuid, vlan):
+ pif = self.pifs[pif_uuid]
+ network = self.networks[network_uuid]
+ return self.PIF_create(pif.name, pif.mtu, vlan, pif.mac, network)
+
+
+ def PIF_destroy(self, pif_uuid):
+ del self.pifs[pif_uuid]
+ self.save_PIFs()
+
def save(self):
# save state
@@ -133,14 +170,16 @@ class XendNode:
'name_description':self.desc}}
self.state_store.save_state('host',host_record)
self.state_store.save_state('cpu', self.cpus)
+ self.save_PIFs()
+ self.save_networks()
+
+ sr_record = {self.sr.uuid: self.sr.get_record()}
+ self.state_store.save_state('sr', sr_record)
+
+ def save_PIFs(self):
pif_records = dict([(k, v.get_record(transient = False))
for k, v in self.pifs.items()])
self.state_store.save_state('pif', pif_records)
-
- self.save_networks()
-
- sr_record = {self.sr.uuid: self.sr.get_record()}
- self.state_store.save_state('sr', sr_record)
def save_networks(self):
net_records = dict([(k, v.get_record(transient = False))
@@ -326,7 +365,12 @@ class XendNode:
return dict(self.physinfo())
def info_dict(self):
return dict(self.info())
-
+
+
+ def refreshBridges(self):
+ for pif in self.pifs.values():
+ pif.refresh(Brctl.get_state())
+
def instance():
global inst
diff -r 069d1364af53 -r a8e853aecb3e tools/python/xen/xend/XendPIF.py
--- a/tools/python/xen/xend/XendPIF.py Wed Dec 27 15:39:32 2006 +0000
+++ b/tools/python/xen/xend/XendPIF.py Wed Dec 27 15:42:56 2006 +0000
@@ -15,16 +15,18 @@
# Copyright (c) 2006 Xensource Inc.
#============================================================================
+import commands
+import logging
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:]+)'
+log = logging.getLogger("xend.XendPIF")
+log.setLevel(logging.TRACE)
+
+
+MAC_RE = re.compile(':'.join(['[0-9a-f]{2}'] * 6))
+IP_IFACE_RE = re.compile(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)
@@ -40,7 +42,7 @@ def linux_get_phy_ifaces():
@rtype: array of 3-element tuple (name, mtu, mac)
"""
- ip_cmd = '/sbin/ip -o link show'
+ ip_cmd = 'ip -o link show'
rc, output = commands.getstatusoutput(ip_cmd)
ifaces = {}
phy_ifaces = []
@@ -66,7 +68,7 @@ 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' % \
+ ip_mac_cmd = 'ip link set %s addr %s' % \
(linux_phy_to_virt(iface), mac)
rc, output = commands.getstatusoutput(ip_mac_cmd)
if rc == 0:
@@ -76,7 +78,7 @@ def linux_set_mac(iface, mac):
def linux_set_mtu(iface, mtu):
try:
- ip_mtu_cmd = '/sbin/ip link set %s mtu %d' % \
+ ip_mtu_cmd = 'ip link set %s mtu %d' % \
(linux_phy_to_virt(iface), int(mtu))
rc, output = commands.getstatusoutput(ip_mtu_cmd)
if rc == 0:
@@ -84,17 +86,6 @@ def linux_set_mtu(iface, mtu):
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."""
@@ -140,3 +131,68 @@ class XendPIF:
result['io_read_kbs'] = str(self.get_io_read_kbs())
result['io_write_kbs'] = str(self.get_io_write_kbs())
return result
+
+
+ def refresh(self, bridges):
+ ifname = self._ifname()
+ rc, _ = _cmd('ip link show %s', ifname)
+ if rc != 0:
+ # Interface does not exist. If it's a physical interface, then
+ # there's nothing we can do -- this should have been set up with
+ # the network script. Otherwise, we can use vconfig to derive
+ # a subinterface.
+ if not self.vlan:
+ return
+
+ rc, _ = _cmd('vconfig add %s %s', self.name, self.vlan)
+ if rc != 0:
+ log.error('Could not refresh %s', ifname)
+ return
+ log.info('Created network interface %s', ifname)
+
+ for brname, nics in bridges.items():
+ if ifname in nics:
+ log.debug('%s is already attached to %s', ifname, brname)
+ return
+
+ # The interface is not attached to a bridge. Create one, and attach
+ # the interface to it.
+ brname = _new_bridge_name(bridges)
+ rc, _ = _cmd('brctl addbr %s', brname)
+ if rc != 0:
+ log.error('Could not create bridge %s for interface %s', brname,
+ ifname)
+ return
+ log.info('Created network bridge %s', brname)
+
+ rc, _ = _cmd('brctl addif %s %s', brname, ifname)
+ if rc != 0:
+ log.error('Could not add %s to %s', ifname, brname)
+ return
+ log.info('Added network interface %s to bridge %s', ifname, brname)
+
+
+ def _ifname(self):
+ if self.vlan:
+ return '%s.%s' % (self.name, self.vlan)
+ else:
+ return self.name
+
+
+def _cmd(cmd, *args):
+ if len(args) > 0:
+ cmd = cmd % args
+ rc, output = commands.getstatusoutput(cmd)
+ if rc != 0:
+ log.debug('%s failed with code %d' % (cmd, rc))
+ log.trace('%s: %s' % (cmd, output))
+ return rc, output
+
+
+def _new_bridge_name(bridges):
+ n = 0
+ while True:
+ brname = 'xenbr%d' % n
+ if brname not in bridges:
+ return brname
+ n += 1
diff -r 069d1364af53 -r a8e853aecb3e tools/python/xen/xend/server/SrvServer.py
--- a/tools/python/xen/xend/server/SrvServer.py Wed Dec 27 15:39:32 2006 +0000
+++ b/tools/python/xen/xend/server/SrvServer.py Wed Dec 27 15:42:56 2006 +0000
@@ -48,7 +48,7 @@ from threading import Thread
from xen.web.httpserver import HttpServer, UnixHttpServer
-from xen.xend import XendRoot, XendAPI
+from xen.xend import XendNode, XendRoot, XendAPI
from xen.xend import Vifctl
from xen.xend.XendLogging import log
from xen.xend.XendClient import XEN_API_SOCKET
@@ -100,6 +100,8 @@ class XendServers:
signal.signal(signal.SIGHUP, self.reloadConfig)
while True:
+ XendNode.instance().refreshBridges()
+
threads = []
for server in self.servers:
if server.ready:
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|