[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Added network.{create, destroy}, and PIF.{create, create_VLAN, destroy}, and
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |