WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [XEND] Fully implement XenAPI network and

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [XEND] Fully implement XenAPI network and PIF classes.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 26 Apr 2007 10:01:40 -0700
Delivery-date: Thu, 26 Apr 2007 10:01:33 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Tom Wilkie <tom.wilkie@xxxxxxxxx>
# Date 1177514271 -3600
# Node ID 0bbc44c0b6e335bb08fc74b0dc1ec4ae6ed39b4b
# Parent  31f6f85778e5b8c8612e1712886cdef566284e1f
[XEND] Fully implement XenAPI network and PIF classes.

Now support creation of Networks and PIFs.  Auto discover current network 
settings.

signed-off-by: Tom Wilkie <tom.wilkie@xxxxxxxxx>
---
 tools/python/xen/xend/XendNetwork.py |  158 +++++++++++++---
 tools/python/xen/xend/XendNode.py    |  260 ++++++++++++---------------
 tools/python/xen/xend/XendPIF.py     |  332 ++++++++++++++++++++++++-----------
 3 files changed, 480 insertions(+), 270 deletions(-)

diff -r 31f6f85778e5 -r 0bbc44c0b6e3 tools/python/xen/xend/XendNetwork.py
--- a/tools/python/xen/xend/XendNetwork.py      Wed Apr 25 16:16:21 2007 +0100
+++ b/tools/python/xen/xend/XendNetwork.py      Wed Apr 25 16:17:51 2007 +0100
@@ -24,15 +24,122 @@ import XendDomain
 import XendDomain
 import XendNode
 from XendLogging import log
+from xen.xend import uuid as genuuid
+from xen.xend.XendBase import XendBase
+from xen.xend.XendError import *
+from xen.util import Brctl
+from xen.xend import XendAPIStore
 
 IP_ROUTE_RE = r'^default via ([\d\.]+) dev (\w+)'
 
-class XendNetwork:
-    def __init__(self, uuid, record):
-        self.uuid = uuid
-        self.name_label = record.get('name_label', '')
-        self.name_description = record.get('name_description', '')
-        self.other_config = record.get('other_config', {})
+def bridge_exists(name):
+    return name in Brctl.get_state().keys()
+
+class XendNetwork(XendBase):
+    """We're going to assert that the name_label of this
+    network is just the name of the bridge"""
+
+    def getClass(self):
+        return "network"
+
+    def getAttrRW(self):
+        attrRW = ['name_label',
+                  'name_description',
+                  'other_config',
+                  'default_gateway',
+                  'default_netmask']
+        return XendBase.getAttrRW() + attrRW
+
+    def getAttrRO(self):
+        attrRO =  ['VIFs',
+                   'PIFs']
+        return XendBase.getAttrRO() + attrRO
+
+    def getAttrInst(self):
+        return XendBase.getAttrInst() + self.getAttrRW()
+
+    def getMethods(self):
+        methods = ['add_to_other_config',
+                   'remove_from_other_config']
+        return XendBase.getMethods() + methods
+
+    def getFuncs(self):
+        funcs = ['create']
+        return XendBase.getFuncs() + funcs
+
+    getClass    = classmethod(getClass)
+    getAttrRO   = classmethod(getAttrRO)
+    getAttrRW   = classmethod(getAttrRW)
+    getAttrInst = classmethod(getAttrInst)
+    getMethods  = classmethod(getMethods)
+    getFuncs    = classmethod(getFuncs)
+
+    def create_phy(self, name):
+        """
+        Called when a new bridge is found on xend start
+        """
+        # Create new uuids
+        uuid = genuuid.createString()
+
+        # Create instance
+        record = {
+                'name_label':       name,
+                'name_description': '',
+                'other_config':     {},
+                'default_gateway':  '',
+                'default_netmask':  ''
+            }
+        network = XendNetwork(record, uuid)
+
+        return uuid
+        
+    def recreate(self, record, uuid):
+        """
+        Called on xend start / restart, or machine
+        restart, when read from saved config.
+        Needs to check network exists, create it otherwise
+        """
+
+        # Create instance (do this first, to check record)
+        network = XendNetwork(record, uuid)
+
+        # Create network if it doesn't already exist
+        if not bridge_exists(network.name_label):
+            Brctl.bridge_create(network.name_label)
+
+        return uuid
+
+    def create(self, record):
+        """
+        Called from API, to create a new network
+        """
+        # Create new uuids
+        uuid = genuuid.createString()
+
+        # Create instance (do this first, to check record)
+        network = XendNetwork(record, uuid)
+
+        # Check network doesn't already exist
+        name_label = network.name_label
+        if bridge_exists(name_label):
+            del network
+            raise UniqueNameError(name_label, "network")
+
+        # Create the bridge
+        Brctl.bridge_create(network.name_label)
+
+        return uuid
+
+    create_phy  = classmethod(create_phy)
+    recreate    = classmethod(recreate)
+    create      = classmethod(create)
+        
+    def __init__(self, record, uuid):       
+        XendBase.__init__(self, uuid, record)
+        
+    #
+    # XenAPI Mehtods
+    #
 
     def get_name_label(self):
         return self.name_label
@@ -41,9 +148,8 @@ class XendNetwork:
         return self.name_description
 
     def set_name_label(self, new_name):
-        self.name_label = new_name
-        XendNode.instance().save_networks()
-
+        pass
+        
     def set_name_description(self, new_desc):
         self.name_description = new_desc
         XendNode.instance().save_networks()
@@ -55,13 +161,14 @@ class XendNetwork:
             vifs = vm.get_vifs()
             for vif in vifs:
                 vif_cfg = vm.get_dev_xenapi_config('vif', vif)
-                if vif_cfg.get('network') == self.uuid:
+                if vif_cfg.get('network') == self.get_uuid():
                     result.append(vif)
         return result
 
     def get_PIFs(self):
-        return [x.uuid for x in XendNode.instance().pifs.values()
-                if x.network == self]
+        pifs = XendAPIStore.get_all("PIF")
+        return [pif.get_uuid() for pif in pifs
+                if pif.get_network() == self.get_uuid()]
 
     def get_other_config(self):
         return self.other_config
@@ -79,17 +186,16 @@ class XendNetwork:
             del self.other_config[key]
         XendNode.instance().save_networks()
 
-    def get_record(self):
-        return self.get_record_internal(True)
-
-    def get_record_internal(self, transient):
-        result = {
-            'uuid': self.uuid,
-            'name_label': self.name_label,
-            'name_description': self.name_description,
-            'other_config' : self.other_config,
-        }
-        if transient:
-            result['VIFs'] = self.get_VIFs()
-            result['PIFs'] = self.get_PIFs()
-        return result
+    def get_default_gateway(self):
+        return self.default_gateway
+
+    def set_default_gateway(self, gateway):
+        self.default_gateway = gateway
+        XendNode.instance().save_networks()
+
+    def get_default_netmask(self):
+        return self.default_netmask
+
+    def set_default_netmask(self, netmask):
+        self.default_netmask = netmask
+        XendNode.instance().save_networks()
diff -r 31f6f85778e5 -r 0bbc44c0b6e3 tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Wed Apr 25 16:16:21 2007 +0100
+++ b/tools/python/xen/xend/XendNode.py Wed Apr 25 16:17:51 2007 +0100
@@ -21,9 +21,10 @@ import xen.lowlevel.xc
 import xen.lowlevel.xc
 
 from xen.util import Brctl
+from xen.xend import XendAPIStore
 
 import uuid, arch
-import XendPBD
+from XendPBD import XendPBD
 from XendError import *
 from XendOptions import instance as xendoptions
 from XendQCoWStorageRepo import XendQCoWStorageRepo
@@ -34,7 +35,7 @@ from XendNetwork import *
 from XendNetwork import *
 from XendStateStore import XendStateStore
 from XendMonitor import XendMonitor
-
+     
 class XendNode:
     """XendNode - Represents a Domain 0 Host."""
     
@@ -133,70 +134,72 @@ class XendNode:
                       'features' : cpu_features,
                     })
 
-        self.pifs = {}
-        self.pif_metrics = {}
-        self.networks = {}
         self.srs = {}
-        
-        # initialise networks
+
+        # Initialise networks
+        # First configure ones off disk
         saved_networks = self.state_store.load_state('network')
         if saved_networks:
             for net_uuid, network in saved_networks.items():
-                self.network_create(network, False, net_uuid)
-        else:
-            bridges = Brctl.get_state().keys()
-            for bridge in bridges:
-                self.network_create({'name_label' : bridge }, False)
+                XendNetwork.recreate(network, net_uuid)
                 
-        # Get a mapping from interface to bridge
-
-        if_to_br = dict([(i,b)
-                         for (b,ifs) in Brctl.get_state().items()
-                         for i in ifs])
-
-        # initialise PIFs
+        # Next discover any existing bridges and check
+        # they are not already configured
+        bridges = Brctl.get_state().keys()
+        configured_bridges = [XendAPIStore.get(
+                                  network_uuid, "network")
+                                      .get_name_label()
+                              for network_uuid in XendNetwork.get_all()]
+        unconfigured_bridges = [bridge
+                                for bridge in bridges
+                                if bridge not in configured_bridges]
+        for unconfigured_bridge in unconfigured_bridges:
+            XendNetwork.create_phy(unconfigured_bridge)
+
+        # Initialise PIFs
+        # First configure ones off disk
         saved_pifs = self.state_store.load_state('pif')
         if saved_pifs:
             for pif_uuid, pif in saved_pifs.items():
-                if pif.get('network') in self.networks:
-                    network = self.networks[pif['network']]
-                    try:
-                        if 'device' not in pif and 'name' in pif:
-                            # Compatibility hack, can go pretty soon.
-                            pif['device'] = pif['name']
-                        if 'metrics' not in pif:
-                            # Compatibility hack, can go pretty soon.
-                            pif['metrics'] = uuid.createString()
-
-                        try:
-                            pif['VLAN'] = int(pif.get('VLAN', -1))
-                        except (ValueError, TypeError):
-                            pif['VLAN'] = -1
-
-                        self._PIF_create(pif['device'], pif['MTU'],
-                                         pif['VLAN'],
-                                         pif['MAC'], network, False, pif_uuid,
-                                         pif['metrics'])
-                    except NetworkAlreadyConnected, exn:
-                        log.error('Cannot load saved PIF %s, as network %s ' +
-                                  'is already connected to PIF %s',
-                                  pif_uuid, pif['network'], exn.pif_uuid)
-        else:
-            for name, mtu, mac in linux_get_phy_ifaces():
-                bridge_name = if_to_br.get(name, None)
-                if bridge_name is not None:
-                    networks = [network for
-                                network in self.networks.values()
-                                if network.get_name_label() == bridge_name]
-                    if len(networks) > 0:
-                        network = networks[0]
-                        self._PIF_create(name, mtu, -1, mac, network, False)
-
+                XendPIF.recreate(pif, pif_uuid)
+ 
+        # Next discover any existing PIFs and check
+        # they are not already configured
+        configured_pifs = [XendAPIStore.get(
+                               pif_uuid, "PIF")
+                                   .get_interface_name()
+                           for pif_uuid in XendPIF.get_all()]
+        unconfigured_pifs = [(name, mtu, mac)
+                             for name, mtu, mac in linux_get_phy_ifaces()
+                             if name not in configured_pifs]
+
+        # Get a mapping from interface to bridge          
+        if_to_br = dict([(i,b)
+                         for (b,ifs) in Brctl.get_state().items()
+                             for i in ifs])
+
+        for name, mtu, mac in unconfigured_pifs:
+            # Check PIF is on bridge
+            # if not, ignore
+            bridge_name = if_to_br.get(name, None)
+            if bridge_name is not None:
+                # Translate bridge name to network uuid
+                for network_uuid in XendNetwork.get_all():
+                    network = XendAPIStore.get(
+                        network_uuid, 'network')
+                    if network.get_name_label() == bridge_name:
+                        XendPIF.create_phy(network_uuid, name,
+                                           mtu, mac)
+                        break
+                else:
+                    log.debug("Cannot find network for bridge %s "
+                              "when configuring PIF %s",
+                              (bridge_name, name))     
+        
         # initialise storage
         saved_srs = self.state_store.load_state('sr')
         if saved_srs:
             for sr_uuid, sr_cfg in saved_srs.items():
-                log.error("SAved SRS %s %s", sr_uuid, sr_cfg['type'])
                 if sr_cfg['type'] == 'qcow_file':
                     self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid)
                 elif sr_cfg['type'] == 'local':
@@ -214,69 +217,47 @@ class XendNode:
         saved_pbds = self.state_store.load_state('pbd')
         if saved_pbds:
             for pbd_uuid, pbd_cfg in saved_pbds.items():
-                pbd_cfg['uuid'] = pbd_uuid
-                XendPBD.XendPBD(pbd_cfg)
-
-
-    def network_create(self, record, persist = True, net_uuid = None):
-        if net_uuid is None:
-            net_uuid = uuid.createString()
-        self.networks[net_uuid] = XendNetwork(net_uuid, record)
-        if persist:
-            self.save_networks()
-        return net_uuid
-
-
-    def network_destroy(self, net_uuid):
-        del self.networks[net_uuid]
-        self.save_networks()
-
-
-    def get_PIF_refs(self):
-        return self.pifs.keys()
-
-
-    def _PIF_create(self, name, mtu, vlan, mac, network, persist = True,
-                    pif_uuid = None, metrics_uuid = None):
-        for pif in self.pifs.values():
-            if pif.network == network:
-                raise NetworkAlreadyConnected(pif.uuid)
-
-        if pif_uuid is None:
-            pif_uuid = uuid.createString()
-        if metrics_uuid is None:
-            metrics_uuid = uuid.createString()
-
-        metrics = XendPIFMetrics(metrics_uuid)
-        pif = XendPIF(pif_uuid, metrics, name, mtu, vlan, mac, network, self)
-        metrics.set_PIF(pif)
-
-        self.pif_metrics[metrics_uuid] = metrics
-        self.pifs[pif_uuid] = pif
-
-        if persist:
-            self.save_PIFs()
-            self.refreshBridges()
-        return pif_uuid
-
-
-    def PIF_create_VLAN(self, pif_uuid, network_uuid, vlan):
-        if vlan < 0 or vlan >= 4096:
-            raise VLANTagInvalid()
-            
-        pif = self.pifs[pif_uuid]
-        network = self.networks[network_uuid]
-        return self._PIF_create(pif.device, pif.mtu, vlan, pif.mac, network)
-
-
-    def PIF_destroy(self, pif_uuid):
-        pif = self.pifs[pif_uuid]
-
-        if pif.vlan == -1:
-            raise PIFIsPhysical()
-
-        del self.pifs[pif_uuid]
-        self.save_PIFs()
+                XendPBD.recreate(pbd_uuid, pbd_cfg)
+
+##    def network_destroy(self, net_uuid):
+ ##       del self.networks[net_uuid]
+  ##      self.save_networks()
+
+
+##    def get_PIF_refs(self):
+##       return self.pifs[:]
+
+##   def _PIF_create(self, name, mtu, vlan, mac, network, persist = True,
+##                     pif_uuid = None, metrics_uuid = None):
+##         for pif in self.pifs.values():
+##             if pif.network == network:
+##                 raise NetworkAlreadyConnected(pif.uuid)
+
+##         if pif_uuid is None:
+##             pif_uuid = uuid.createString()
+##         if metrics_uuid is None:
+##             metrics_uuid = uuid.createString()
+
+##         metrics = XendPIFMetrics(metrics_uuid)
+##         pif = XendPIF(pif_uuid, metrics, name, mtu, vlan, mac, network, 
self)
+##         metrics.set_PIF(pif)
+
+##         self.pif_metrics[metrics_uuid] = metrics
+##         self.pifs[pif_uuid] = pif
+
+##         if persist:
+##             self.save_PIFs()
+##             self.refreshBridges()
+##         return pif_uuid
+
+##     def PIF_destroy(self, pif_uuid):
+##         pif = self.pifs[pif_uuid]
+
+##         if pif.vlan == -1:
+##             raise PIFIsPhysical()
+
+##         del self.pifs[pif_uuid]
+##         self.save_PIFs()
 
 
     def save(self):
@@ -284,7 +265,7 @@ class XendNode:
         host_record = {self.uuid: {'name_label':self.name,
                                    'name_description':self.desc,
                                    'metrics_uuid': self.host_metrics_uuid,
-                                   'other_config': repr(self.other_config)}}
+                                   'other_config': self.other_config}}
         self.state_store.save_state('host',host_record)
         self.state_store.save_state('cpu', self.cpus)
         self.save_PIFs()
@@ -293,18 +274,21 @@ class XendNode:
         self.save_SRs()
 
     def save_PIFs(self):
-        pif_records = dict([(k, v.get_record())
-                            for k, v in self.pifs.items()])
+        pif_records = dict([(pif_uuid, XendAPIStore.get(
+                                 pif_uuid, "PIF").get_record())
+                            for pif_uuid in XendPIF.get_all()])
         self.state_store.save_state('pif', pif_records)
 
     def save_networks(self):
-        net_records = dict([(k, v.get_record_internal(False))
-                            for k, v in self.networks.items()])
+        net_records = dict([(network_uuid, XendAPIStore.get(
+                                 network_uuid, "network").get_record())
+                            for network_uuid in XendNetwork.get_all()])
         self.state_store.save_state('network', net_records)
 
     def save_PBDs(self):
-        pbd_records = dict([(v.get_uuid(), v.get_record())
-                            for v in XendPBD.get_all()])
+        pbd_records = dict([(pbd_uuid, XendAPIStore.get(
+                                 pbd_uuid, "PBD").get_record())
+                            for pbd_uuid in XendPBD.get_all()])
         self.state_store.save_state('pbd', pbd_records)
 
     def save_SRs(self):
@@ -330,9 +314,6 @@ class XendNode:
 
     def is_valid_cpu(self, cpu_ref):
         return (cpu_ref in self.cpus)
-
-    def is_valid_network(self, network_ref):
-        return (network_ref in self.networks)
 
     def is_valid_sr(self, sr_ref):
         return (sr_ref in self.srs)
@@ -495,12 +476,6 @@ class XendNode:
     # Network Functions
     #
     
-    def get_network_refs(self):
-        return self.networks.keys()
-
-    def get_network(self, network_ref):
-        return self.networks[network_ref]
-
     def bridge_to_network(self, bridge):
         """
         Determine which network a particular bridge is attached to.
@@ -518,13 +493,12 @@ class XendNode:
                 raise Exception(
                     'Could not find default bridge, and none was specified')
 
-        bridges = Brctl.get_state()
-        if bridge not in bridges:
-            raise Exception('Bridge %s is not up' % bridge)
-        for pif in self.pifs.values():
-            if pif.interface_name() in bridges[bridge]:
-                return pif.network
-        raise Exception('Bridge %s is not connected to a network' % bridge)
+        for network_uuid in XendNetwork.get_all():
+            network = XendAPIStore.get(network_uuid, "network")
+            if network.get_name_label() == bridge:
+                return network
+        else:
+            raise Exception('Cannot find network for bridge %s' % bridge)
 
     #
     # Debug keys.
@@ -641,12 +615,6 @@ 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 parse_proc_cpuinfo():
     cpuinfo = {}
diff -r 31f6f85778e5 -r 0bbc44c0b6e3 tools/python/xen/xend/XendPIF.py
--- a/tools/python/xen/xend/XendPIF.py  Wed Apr 25 16:16:21 2007 +0100
+++ b/tools/python/xen/xend/XendPIF.py  Wed Apr 25 16:17:51 2007 +0100
@@ -19,11 +19,14 @@ import logging
 import logging
 import os
 import re
-
+from xen.xend import uuid as genuuid
+from xen.xend import XendAPIStore
+from xen.xend.XendBase import XendBase
+from xen.xend.XendPIFMetrics import XendPIFMetrics
+from xen.xend.XendError import *
 
 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:]+)')
@@ -87,106 +90,239 @@ def linux_set_mtu(iface, mtu):
     except ValueError:
         return False
 
-class XendPIF:
+def _create_VLAN(dev, vlan):
+    rc, _ = commands.getstatusoutput('vconfig add %s %d' %
+                                     (dev, vlan))
+    return rc == 0   
+
+class XendPIF(XendBase):
     """Representation of a Physical Network Interface."""
-    
-    def __init__(self, uuid, metrics, device, mtu, vlan, mac, network,
-                 host):
-        self.uuid = uuid
-        self.metrics = metrics
-        self.device = device
-        self.mac = mac
-        self.mtu = mtu
-        self.vlan = vlan
-        self.network = network
-        self.host = host
-
-    def set_device(self, new_device):
-        self.device = new_device
-
-    def set_mac(self, new_mac):
-        success = linux_set_mac(new_mac)
+
+    def getClass(self):
+        return "PIF"
+
+    def getAttrRO(self):
+        attrRO = ['network',
+                  'host',
+                  'metrics',
+                  'device']
+        return XendBase.getAttrRO() + attrRO
+    
+    def getAttrRW(self):
+        attrRW = ['MAC',
+                  'MTU',
+                  'VLAN']
+        return XendBase.getAttrRW() + attrRW
+
+    def getAttrInst(self):
+        attrInst = ['network',
+                    'device',
+                    'MAC',
+                    'MTU',
+                    'VLAN']
+        return attrInst
+
+    def getMethods(self):
+        methods = ['plug',
+                   'unplug']
+        return XendBase.getMethods() + methods
+
+    def getFuncs(self):
+        funcs = ['create_VLAN']
+        return XendBase.getFuncs() + funcs
+
+    getClass    = classmethod(getClass)
+    getAttrRO   = classmethod(getAttrRO)
+    getAttrRW   = classmethod(getAttrRW)
+    getAttrInst = classmethod(getAttrInst)
+    getMethods  = classmethod(getMethods)
+    getFuncs    = classmethod(getFuncs)
+    
+    def create_phy(self, network_uuid, device,
+                   MAC, MTU):
+        """
+        Called when a new physical PIF is found
+        Could be a VLAN...
+        """
+        # Create new uuids
+        pif_uuid = genuuid.createString()
+        metrics_uuid = genuuid.createString()
+
+        # Create instances
+        metrics = XendPIFMetrics(metrics_uuid, pif_uuid)
+
+        # Is this a VLAN?
+        VLANdot = device.split(".")
+        VLANcolon = device.split(":")
+
+        if len(VLANdot) > 1:
+            VLAN = VLANdot[1]
+            device = VLANdot[0]
+        elif len(VLANcolon) > 1:
+            VLAN = VLANcolon[1]
+            device = VLANcolon[0] 
+        else:
+            VLAN = -1
+            
+        record = {
+            'network': network_uuid,
+            'device':  device,
+            'MAC':     MAC,
+            'MTU':     MTU,
+            'VLAN':    VLAN
+            }
+        pif = XendPIF(record, pif_uuid, metrics_uuid)
+
+        return pif_uuid
+
+    def recreate(self, record, uuid):
+        """Called on xend start / restart"""        
+        pif_uuid = uuid
+        metrics_uuid = record['metrics']
+
+        # Create instances
+        metrics = XendPIFMetrics(metrics_uuid, pif_uuid)
+        pif = XendPIF(record, pif_uuid, metrics_uuid)
+
+        # If physical PIF, check exists
+        # If VLAN, create if not exist
+        ifs = [dev for dev, _1, _2 in linux_get_phy_ifaces()]
+        if pif.get_VLAN() == -1:
+            if pif.get_device() not in ifs:
+                del pif
+                del metrics
+                return None
+        else:
+            if pif.get_interface_name() not in ifs:
+                _create_VLAN(pif.get_device(), pif.get_VLAN())
+
+        return pif_uuid
+
+    def create_VLAN(self, device, network_uuid, host_ref, vlan):
+        """Exposed via API - create a new VLAN from existing VIF"""
+        
+        ifs = [name for name, _, _ in linux_get_phy_ifaces()]
+
+        vlan = int(vlan)
+
+        # Check VLAN tag is valid
+        if vlan < 0 or vlan >= 4096:
+            raise VLANTagInvalid(vlan)
+        
+        # Check device exists
+        if device not in ifs:
+            raise InvalidDeviceError(device)
+
+        # Check VLAN doesn't already exist
+        if "%s.%d" % (device, vlan) in ifs:
+            raise DeviceExistsError("%s.%d" % (device, vlan))
+
+        # Check network ref is valid
+        from xen.xend import XendNode
+        network_uuids = XendNode.instance().networks
+        if network_uuid in network_uuids:
+            raise InvalidHandleError("Network", network_ref)
+
+        # Check host_ref is this host
+        if host_ref != XendNode.instance().get_uuid():
+            raise InvalidHandleError("Host", host_ref)
+
+        # Create the VLAN
+        _create_VLAN(device, vlan)
+
+        # Create new uuids
+        pif_uuid = genuuid.createString()
+        metrics_uuid = genuuid.createString()
+
+        # Create the record
+        record = {
+            "device":  device,
+            "MAC":     '',
+            "MTU":     '',
+            "network": network_ref,
+            "VLAN":    vlan
+            }
+
+        # Create instances
+        metrics = XendPIFMetrics(metrics_uuid, pif_uuid)
+        pif = XendPIF(record, pif_uuid, metrics_uuid)
+        
+        # Add it to list of PIFs
+        XendNode.instance().pifs.append(pif_ref)        
+
+        # Add it to network
+        network.add_pif(pif_ref)
+
+        return pif_uuid
+
+    create_phy  = classmethod(create_phy)
+    recreate    = classmethod(recreate)
+    create_VLAN = classmethod(create_VLAN)
+    
+    def __init__(self, record, uuid, metrics_uuid):
+        XendBase.__init__(self, uuid, record)
+        self.metrics = metrics_uuid
+
+    def plug(self):
+        """Plug the PIF into the network"""
+        network = XendAPIStore.get(self.network,
+                                   "network")
+        bridge_name = network.get_name_label()
+
+        Brctl.vif_bridge_add({
+            "bridge": bridge_name,
+            "vif":    self.get_interface_name()
+            })
+
+    def unplug(self):
+        """Unplug the PIF from the network"""
+        pass
+
+    def get_interface_name(self):
+        if self.get_VLAN() == -1:
+            return self.get_device()
+        else:
+            return "%s.%d" % (self.get_device(), self.get_VLAN())
+        
+    def get_device(self):
+        """
+        This is the base interface.
+        For phy if (VLAN == -1) this is same as
+        if name.
+        For VLANs, this it the bit before the period
+        """
+        return self.device
+
+    def get_network(self):
+        return self.network
+
+    def get_host(self):
+        from xen.xend import XendNode
+        return XendNode.instance().get_uuid()
+
+    def get_metrics(self):
+        return self.metrics
+
+    def get_MAC(self):
+        return self.MAC
+
+    def set_MAC(self, new_mac):
+        success = linux_set_mac(self.device, new_mac)
         if success:
-            self.mac = new_mac
+            self.MAC = new_mac
         return success
 
-    def set_mtu(self, new_mtu):
-        success = linux_set_mtu(new_mtu)
+    def get_MTU(self):
+        return self.MTU
+
+    def set_MTU(self, new_mtu):
+        success = linux_set_mtu(self.device, new_mtu)
         if success:
-            self.mtu = new_mtu
+            self.MTU = new_mtu
         return success
 
-    def get_record(self):
-        return {'uuid': self.uuid,
-                'device': self.device,
-                'MAC': self.mac,
-                'MTU': self.mtu,
-                'VLAN': self.vlan,
-                'host': self.host.uuid,
-                'network': self.network.uuid,
-                'metrics': self.metrics.uuid}
-
-    def refresh(self, bridges):
-        ifname = self.interface_name()
-        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 self.vlan == -1:
-                return
-            
-            rc, _ = _cmd('vconfig add %s %d', self.device, self.vlan)
-            if rc != 0:
-                log.error('Could not refresh VLAN for interface %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 interface_name(self):
-        if self.vlan != -1:
-            return '%s.%d' % (self.device, self.vlan)
-        else:
-            return self.device
-
-
-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
+    def get_VLAN(self):
+        return self.VLAN
+
+    def set_VLAN(self, VLAN):
+        pass

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [XEND] Fully implement XenAPI network and PIF classes., Xen patchbot-unstable <=