Setting tag sliver-openvswitch-2.2.90-1
[sliver-openvswitch.git] / xenserver / opt_xensource_libexec_InterfaceReconfigure.py
index 3c3a019..f37e038 100644 (file)
@@ -241,20 +241,27 @@ def _strlist_from_xml(n, ltag, itag):
             ret.append(_str_from_xml(n))
     return ret
 
             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():
     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
 
     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.
 #
 #
 # 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"
 
 _PIF_XML_TAG = "pif"
 _VLAN_XML_TAG = "vlan"
+_TUNNEL_XML_TAG = "tunnel"
 _BOND_XML_TAG = "bond"
 _NETWORK_XML_TAG = "network"
 _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' ] + \
 
 _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),
                         _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')),
                '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),
                '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),
               }
 
                 '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')),
               }
 
 _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),
 
 _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)),
                  }
 
                                     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
 #
 #
 # Database Cache object
 #
@@ -375,18 +404,26 @@ class DatabaseCache(object):
 
     def __get_vlan_records_from_xapi(self, session):
         self.__vlans = {}
 
     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]
 
             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 = {}
     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] = {}
             if not self.__pif_on_host(rec['master']):
                 continue
             self.__bonds[b] = {}
@@ -395,13 +432,16 @@ class DatabaseCache(object):
 
     def __get_network_records_from_xapi(self, session):
         self.__networks = {}
 
     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":
                     # drop PIFs on other hosts
                     self.__networks[n][f] = [p for p in rec[f] if self.__pif_on_host(p)]
             self.__networks[n] = {}
             for f in _NETWORK_ATTRS:
                 if f == "PIFs":
                     # drop PIFs on other hosts
                     self.__networks[n][f] = [p for p in rec[f] if self.__pif_on_host(p)]
+                elif f == "MTU" and f not in rec:
+                    # XenServer 5.5 network records did not have an
+                    # MTU field, so allow this to be missing.
+                    pass
                 else:
                     self.__networks[n][f] = rec[f]
             self.__networks[n]['other_config'] = {}
                 else:
                     self.__networks[n][f] = rec[f]
             self.__networks[n]['other_config'] = {}
@@ -409,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]
 
                 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)
     def __to_xml(self, xml, parent, key, ref, rec, attrs):
         """Encode a database object as XML"""
         e = xml.createElement(key)
@@ -454,7 +508,8 @@ class DatabaseCache(object):
                 host = session.xenapi.host.get_by_uuid(inventory['INSTALLATION_UUID'])
 
                 self.__get_pif_records_from_xapi(session, host)
                 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)
                 self.__get_vlan_records_from_xapi(session)
                 self.__get_bond_records_from_xapi(session)
                 self.__get_network_records_from_xapi(session)
@@ -469,6 +524,8 @@ class DatabaseCache(object):
             self.__pifs = {}
             self.__bonds = {}
             self.__vlans = {}
             self.__pifs = {}
             self.__bonds = {}
             self.__vlans = {}
+            self.__pools = {}
+            self.__tunnels = {}
             self.__networks = {}
 
             assert(len(xml.childNodes) == 1)
             self.__networks = {}
 
             assert(len(xml.childNodes) == 1)
@@ -488,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 == _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 == _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)
 
                 else:
                     raise Error("Unknown XML element %s" % n.nodeName)
 
@@ -504,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)
             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.__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()
         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,
 
     def get_pif_by_uuid(self, uuid):
         pifs = map(lambda (ref,rec): ref,
@@ -528,10 +597,21 @@ class DatabaseCache(object):
                    filter(lambda (ref,rec): rec['device'] == device,
                           self.__pifs.items()))
 
                    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):
     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)
 
         if len(networks) == 0:
             raise Error("No matching network \"%s\"" % bridge)
 
@@ -582,11 +662,16 @@ class DatabaseCache(object):
         else:
             return None
 
         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']
     settings = []
     if oc.has_key('ethtool-speed'):
         val = oc['ethtool-speed']
@@ -596,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']
             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'):
         else:
             log("Invalid value for ethtool-duplex = %s. Must be half|full." % val)
     if oc.has_key('ethtool-autoneg'):
@@ -609,7 +694,7 @@ def ethtool_settings(oc):
         else:
             log("Invalid value for ethtool-autoneg = %s. Must be on|true|off|false." % val)
     offload = []
         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"]:
         if oc.has_key("ethtool-" + opt):
             val = oc["ethtool-" + opt]
             if val in ["true", "on"]:
@@ -618,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))
                 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,
     return settings,offload
 
 # By default the MTU is taken from the Network.MTU setting for VIF,
@@ -786,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'])]
 
     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
 #
 #
 # Datapath base class
 #
@@ -799,6 +892,12 @@ class Datapath(object):
     def __init__(self, pif):
         self._pif = pif
 
     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
     def configure_ipdev(self, cfg):
         """Write ifcfg TYPE field for an IPdev, plus any type specific
            fields to cfg
@@ -824,7 +923,7 @@ class Datapath(object):
 
            Should assume any configuration files changed attached in
            the preconfigure stage are applied and bring up the
 
            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.
            PIF.
 
            Should not bring up the IPdev.
@@ -846,7 +945,7 @@ class Datapath(object):
         """
         raise NotImplementedError
         
         """
         raise NotImplementedError
         
-def DatapathFactory(pif):
+def DatapathFactory():
     # XXX Need a datapath object for bridgeless PIFs
 
     try:
     # XXX Need a datapath object for bridgeless PIFs
 
     try:
@@ -858,9 +957,9 @@ def DatapathFactory(pif):
     
     if network_backend == "bridge":
         from InterfaceReconfigureBridge import DatapathBridge
     
     if network_backend == "bridge":
         from InterfaceReconfigureBridge import DatapathBridge
-        return DatapathBridge(pif)
-    elif network_backend == "vswitch":
+        return DatapathBridge
+    elif network_backend in ["openvswitch", "vswitch"]:
         from InterfaceReconfigureVswitch import DatapathVswitch
         from InterfaceReconfigureVswitch import DatapathVswitch
-        return DatapathVswitch(pif)
+        return DatapathVswitch
     else:
         raise Error("unknown network backend %s" % network_backend)
     else:
         raise Error("unknown network backend %s" % network_backend)