Setting tag sliver-openvswitch-2.2.90-1
[sliver-openvswitch.git] / xenserver / opt_xensource_libexec_InterfaceReconfigure.py
index 9723c66..f37e038 100644 (file)
@@ -241,20 +241,27 @@ def _strlist_from_xml(n, ltag, itag):
             ret.append(_str_from_xml(n))
     return ret
 
-def _otherconfig_to_xml(xml, parent, val, attrs):
-    otherconfig = xml.createElement("other_config")
-    parent.appendChild(otherconfig)
+def _map_to_xml(xml, parent, tag, val, attrs):
+    e = xml.createElement(tag)
+    parent.appendChild(e)
     for n,v in val.items():
-        if not n in attrs:
-            raise Error("Unknown other-config attribute: %s" % n)
-        _str_to_xml(xml, otherconfig, n, v)
-def _otherconfig_from_xml(n, attrs):
+        if n in attrs:
+            _str_to_xml(xml, e, n, v)
+        else:
+            log("Unknown other-config attribute: %s" % n)
+
+def _map_from_xml(n, attrs):
     ret = {}
     for n in n.childNodes:
         if n.nodeName in attrs:
             ret[n.nodeName] = _str_from_xml(n)
     return ret
 
+def _otherconfig_to_xml(xml, parent, val, attrs):
+    return _map_to_xml(xml, parent, "other_config", val, attrs)
+def _otherconfig_from_xml(n, attrs):
+    return _map_from_xml(n, attrs)
+
 #
 # Definitions of the database objects (and their attributes) used by interface-reconfigure.
 #
@@ -267,13 +274,17 @@ def _otherconfig_from_xml(n, attrs):
 
 _PIF_XML_TAG = "pif"
 _VLAN_XML_TAG = "vlan"
+_TUNNEL_XML_TAG = "tunnel"
 _BOND_XML_TAG = "bond"
 _NETWORK_XML_TAG = "network"
+_POOL_XML_TAG = "pool"
 
-_ETHTOOL_OTHERCONFIG_ATTRS = ['ethtool-%s' % x for x in 'autoneg', 'speed', 'duplex', 'rx', 'tx', 'sg', 'tso', 'ufo', 'gso' ]
+_ETHTOOL_OTHERCONFIG_ATTRS = ['ethtool-%s' % x for x in 'autoneg', 'speed', 'duplex', 'rx', 'tx', 'sg', 'tso', 'ufo', 'gso', 'gro', 'lro' ]
 
 _PIF_OTHERCONFIG_ATTRS = [ 'domain', 'peerdns', 'defaultroute', 'mtu', 'static-routes' ] + \
-                        [ 'bond-%s' % x for x in 'mode', 'miimon', 'downdelay', 'updelay', 'use_carrier' ] + \
+                        [ 'bond-%s' % x for x in 'mode', 'miimon', 'downdelay',
+                                'updelay', 'use_carrier', 'hashing-algorithm' ] + \
+                        [ 'vlan-bug-workaround' ] + \
                         _ETHTOOL_OTHERCONFIG_ATTRS
 
 _PIF_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml),
@@ -287,6 +298,10 @@ _PIF_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml),
                'VLAN_master_of': (_str_to_xml,_str_from_xml),
                'VLAN_slave_of': (lambda x, p, t, v: _strlist_to_xml(x, p, 'VLAN_slave_of', 'master', v),
                                  lambda n: _strlist_from_xml(n, 'VLAN_slave_Of', 'master')),
+               'tunnel_access_PIF_of': (lambda x, p, t, v: _strlist_to_xml(x, p, 'tunnel_access_PIF_of', 'pif', v),
+                                        lambda n: _strlist_from_xml(n, 'tunnel_access_PIF_of', 'pif')),
+               'tunnel_transport_PIF_of':  (lambda x, p, t, v: _strlist_to_xml(x, p, 'tunnel_transport_PIF_of', 'pif', v),
+                                            lambda n: _strlist_from_xml(n, 'tunnel_transport_PIF_of', 'pif')),
                'ip_configuration_mode': (_str_to_xml,_str_from_xml),
                'IP': (_str_to_xml,_str_from_xml),
                'netmask': (_str_to_xml,_str_from_xml),
@@ -308,13 +323,21 @@ _VLAN_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml),
                 'untagged_PIF': (_str_to_xml,_str_from_xml),
               }
 
+_TUNNEL_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml),
+                  'access_PIF': (_str_to_xml,_str_from_xml),
+                  'transport_PIF': (_str_to_xml,_str_from_xml),
+                }
 _BOND_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml),
                'master': (_str_to_xml,_str_from_xml),
                'slaves': (lambda x, p, t, v: _strlist_to_xml(x, p, 'slaves', 'slave', v),
                           lambda n: _strlist_from_xml(n, 'slaves', 'slave')),
               }
 
-_NETWORK_OTHERCONFIG_ATTRS = [ 'mtu', 'static-routes' ] + _ETHTOOL_OTHERCONFIG_ATTRS
+_NETWORK_OTHERCONFIG_ATTRS = [ 'mtu',
+                               'static-routes',
+                               'vswitch-controller-fail-mode',
+                               'vswitch-disable-in-band' ] \
+                               + _ETHTOOL_OTHERCONFIG_ATTRS
 
 _NETWORK_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml),
                    'bridge': (_str_to_xml,_str_from_xml),
@@ -325,6 +348,12 @@ _NETWORK_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml),
                                     lambda n: _otherconfig_from_xml(n, _NETWORK_OTHERCONFIG_ATTRS)),
                  }
 
+_POOL_OTHERCONFIG_ATTRS = ['vswitch-controller-fail-mode']
+
+_POOL_ATTRS = { 'other_config': (lambda x, p, t, v: _otherconfig_to_xml(x, p, v, _POOL_OTHERCONFIG_ATTRS),
+                                 lambda n: _otherconfig_from_xml(n, _POOL_OTHERCONFIG_ATTRS)),
+              }
+
 #
 # Database Cache object
 #
@@ -375,18 +404,26 @@ class DatabaseCache(object):
 
     def __get_vlan_records_from_xapi(self, session):
         self.__vlans = {}
-        for v in session.xenapi.VLAN.get_all():
-            rec = session.xenapi.VLAN.get_record(v)
+        for (v,rec) in session.xenapi.VLAN.get_all_records().items():
             if not self.__pif_on_host(rec['untagged_PIF']):
                 continue
             self.__vlans[v] = {}
             for f in _VLAN_ATTRS:
                 self.__vlans[v][f] = rec[f]
 
+    def __get_tunnel_records_from_xapi(self, session):
+        self.__tunnels = {}
+        for t in session.xenapi.tunnel.get_all():
+            rec = session.xenapi.tunnel.get_record(t)
+            if not self.__pif_on_host(rec['transport_PIF']):
+                continue
+            self.__tunnels[t] = {}
+            for f in _TUNNEL_ATTRS:
+                self.__tunnels[t][f] = rec[f]
+
     def __get_bond_records_from_xapi(self, session):
         self.__bonds = {}
-        for b in session.xenapi.Bond.get_all():
-            rec = session.xenapi.Bond.get_record(b)
+        for (b,rec) in session.xenapi.Bond.get_all_records().items():
             if not self.__pif_on_host(rec['master']):
                 continue
             self.__bonds[b] = {}
@@ -395,8 +432,7 @@ class DatabaseCache(object):
 
     def __get_network_records_from_xapi(self, session):
         self.__networks = {}
-        for n in session.xenapi.network.get_all():
-            rec = session.xenapi.network.get_record(n)
+        for (n,rec) in session.xenapi.network.get_all_records().items():
             self.__networks[n] = {}
             for f in _NETWORK_ATTRS:
                 if f == "PIFs":
@@ -413,6 +449,20 @@ class DatabaseCache(object):
                 if not rec['other_config'].has_key(f): continue
                 self.__networks[n]['other_config'][f] = rec['other_config'][f]
 
+    def __get_pool_records_from_xapi(self, session):
+        self.__pools = {}
+        for p in session.xenapi.pool.get_all():
+            rec = session.xenapi.pool.get_record(p)
+
+            self.__pools[p] = {}
+
+            for f in _POOL_ATTRS:
+                self.__pools[p][f] = rec[f]
+
+            for f in _POOL_OTHERCONFIG_ATTRS:
+                if rec['other_config'].has_key(f):
+                    self.__pools[p]['other_config'][f] = rec['other_config'][f]
+
     def __to_xml(self, xml, parent, key, ref, rec, attrs):
         """Encode a database object as XML"""
         e = xml.createElement(key)
@@ -458,7 +508,8 @@ class DatabaseCache(object):
                 host = session.xenapi.host.get_by_uuid(inventory['INSTALLATION_UUID'])
 
                 self.__get_pif_records_from_xapi(session, host)
-
+                self.__get_pool_records_from_xapi(session)
+                self.__get_tunnel_records_from_xapi(session)
                 self.__get_vlan_records_from_xapi(session)
                 self.__get_bond_records_from_xapi(session)
                 self.__get_network_records_from_xapi(session)
@@ -473,6 +524,8 @@ class DatabaseCache(object):
             self.__pifs = {}
             self.__bonds = {}
             self.__vlans = {}
+            self.__pools = {}
+            self.__tunnels = {}
             self.__networks = {}
 
             assert(len(xml.childNodes) == 1)
@@ -492,9 +545,15 @@ class DatabaseCache(object):
                 elif n.nodeName == _VLAN_XML_TAG:
                     (ref,rec) = self.__from_xml(n, _VLAN_ATTRS)
                     self.__vlans[ref] = rec
+                elif n.nodeName == _TUNNEL_XML_TAG:
+                    (ref,rec) = self.__from_xml(n, _TUNNEL_ATTRS)
+                    self.__vlans[ref] = rec
                 elif n.nodeName == _NETWORK_XML_TAG:
                     (ref,rec) = self.__from_xml(n, _NETWORK_ATTRS)
                     self.__networks[ref] = rec
+                elif n.nodeName == _POOL_XML_TAG:
+                    (ref,rec) = self.__from_xml(n, _POOL_ATTRS)
+                    self.__pools[ref] = rec
                 else:
                     raise Error("Unknown XML element %s" % n.nodeName)
 
@@ -508,13 +567,19 @@ class DatabaseCache(object):
             self.__to_xml(xml, xml.documentElement, _BOND_XML_TAG, ref, rec, _BOND_ATTRS)
         for (ref,rec) in self.__vlans.items():
             self.__to_xml(xml, xml.documentElement, _VLAN_XML_TAG, ref, rec, _VLAN_ATTRS)
+        for (ref,rec) in self.__tunnels.items():
+            self.__to_xml(xml, xml.documentElement, _TUNNEL_XML_TAG, ref, rec, _TUNNEL_ATTRS)
         for (ref,rec) in self.__networks.items():
             self.__to_xml(xml, xml.documentElement, _NETWORK_XML_TAG, ref, rec,
                           _NETWORK_ATTRS)
+        for (ref,rec) in self.__pools.items():
+            self.__to_xml(xml, xml.documentElement, _POOL_XML_TAG, ref, rec, _POOL_ATTRS)
 
-        f = open(cache_file, 'w')
+        temp_file = cache_file + ".%d" % os.getpid()
+        f = open(temp_file, 'w')
         f.write(xml.toprettyxml())
         f.close()
+        os.rename(temp_file, cache_file)
 
     def get_pif_by_uuid(self, uuid):
         pifs = map(lambda (ref,rec): ref,
@@ -532,10 +597,21 @@ class DatabaseCache(object):
                    filter(lambda (ref,rec): rec['device'] == device,
                           self.__pifs.items()))
 
+    def get_networks_with_bridge(self, bridge):
+        return map(lambda (ref,rec): ref,
+                  filter(lambda (ref,rec): rec['bridge'] == bridge,
+                         self.__networks.items()))
+
+    def get_network_by_bridge(self, bridge):
+        #Assumes one network has bridge.
+        try:
+            return self.get_networks_with_bridge(bridge)[0]
+        except KeyError:
+            return None
+
     def get_pif_by_bridge(self, bridge):
-        networks = map(lambda (ref,rec): ref,
-                       filter(lambda (ref,rec): rec['bridge'] == bridge,
-                              self.__networks.items()))
+        networks = self.get_networks_with_bridge(bridge)
+
         if len(networks) == 0:
             raise Error("No matching network \"%s\"" % bridge)
 
@@ -586,11 +662,16 @@ class DatabaseCache(object):
         else:
             return None
 
+    def get_pool_record(self):
+        if len(self.__pools) > 0:
+            return self.__pools.values()[0]
+
 #
 #
 #
+PIF_OTHERCONFIG_DEFAULTS = {'gro': 'off', 'lro': 'off'}
 
-def ethtool_settings(oc):
+def ethtool_settings(oc, defaults = {}):
     settings = []
     if oc.has_key('ethtool-speed'):
         val = oc['ethtool-speed']
@@ -600,8 +681,8 @@ def ethtool_settings(oc):
             log("Invalid value for ethtool-speed = %s. Must be 10|100|1000." % val)
     if oc.has_key('ethtool-duplex'):
         val = oc['ethtool-duplex']
-        if val in ["10", "100", "1000"]:
-            settings += ['duplex', 'val']
+        if val in ["half", "full"]:
+            settings += ['duplex', val]
         else:
             log("Invalid value for ethtool-duplex = %s. Must be half|full." % val)
     if oc.has_key('ethtool-autoneg'):
@@ -613,7 +694,7 @@ def ethtool_settings(oc):
         else:
             log("Invalid value for ethtool-autoneg = %s. Must be on|true|off|false." % val)
     offload = []
-    for opt in ("rx", "tx", "sg", "tso", "ufo", "gso"):
+    for opt in ("rx", "tx", "sg", "tso", "ufo", "gso", "gro", "lro"):
         if oc.has_key("ethtool-" + opt):
             val = oc["ethtool-" + opt]
             if val in ["true", "on"]:
@@ -622,6 +703,8 @@ def ethtool_settings(oc):
                 offload += [opt, 'off']
             else:
                 log("Invalid value for ethtool-%s = %s. Must be on|true|off|false." % (opt, val))
+        elif opt in defaults:
+            offload += [opt, defaults[opt]]
     return settings,offload
 
 # By default the MTU is taken from the Network.MTU setting for VIF,
@@ -790,6 +873,12 @@ def pif_get_vlan_masters(pif):
     vlans = [db().get_vlan_record(v) for v in pifrec['VLAN_slave_of']]
     return [v['untagged_PIF'] for v in vlans if v and db().pif_exists(v['untagged_PIF'])]
 
+#
+# Tunnel PIFs
+#
+def pif_is_tunnel(pif):
+    return len(db().get_pif_record(pif)['tunnel_access_PIF_of']) > 0
+
 #
 # Datapath base class
 #
@@ -803,6 +892,12 @@ class Datapath(object):
     def __init__(self, pif):
         self._pif = pif
 
+    @classmethod
+    def rewrite(cls):
+        """Class method called when write action is called. Can be used
+           to update any backend specific configuration."""
+        pass
+
     def configure_ipdev(self, cfg):
         """Write ifcfg TYPE field for an IPdev, plus any type specific
            fields to cfg
@@ -828,7 +923,7 @@ class Datapath(object):
 
            Should assume any configuration files changed attached in
            the preconfigure stage are applied and bring up the
-           necesary devices to provide the datapath for the
+           necessary devices to provide the datapath for the
            PIF.
 
            Should not bring up the IPdev.
@@ -850,7 +945,7 @@ class Datapath(object):
         """
         raise NotImplementedError
         
-def DatapathFactory(pif):
+def DatapathFactory():
     # XXX Need a datapath object for bridgeless PIFs
 
     try:
@@ -862,9 +957,9 @@ def DatapathFactory(pif):
     
     if network_backend == "bridge":
         from InterfaceReconfigureBridge import DatapathBridge
-        return DatapathBridge(pif)
+        return DatapathBridge
     elif network_backend in ["openvswitch", "vswitch"]:
         from InterfaceReconfigureVswitch import DatapathVswitch
-        return DatapathVswitch(pif)
+        return DatapathVswitch
     else:
         raise Error("unknown network backend %s" % network_backend)