[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.