netdev: do not allow devices to be opened with conflicting types
[cascardo/ovs.git] / xenserver / opt_xensource_libexec_InterfaceReconfigure.py
index e99ae58..74b784d 100644 (file)
@@ -44,7 +44,8 @@ def log(s):
     if get_log_destination() == 'syslog':
         syslog.syslog(s)
     else:
-        print >>sys.stderr, s
+        sys.stderr.write(s + '\n')
+        sys.stderr.flush()
 
 #
 # Exceptions.
@@ -279,10 +280,11 @@ _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),
@@ -331,7 +333,11 @@ _BOND_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml),
                           lambda n: _strlist_from_xml(n, 'slaves', 'slave')),
               }
 
-_NETWORK_OTHERCONFIG_ATTRS = [ 'mtu', 'static-routes', 'vswitch-controller-fail-mode' ] + _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),
@@ -381,7 +387,7 @@ class DatabaseCache(object):
         return dict(defs)
 
     def __pif_on_host(self,pif):
-        return self.__pifs.has_key(pif)
+        return pif in self.__pifs
 
     def __get_pif_records_from_xapi(self, session, host):
         self.__pifs = {}
@@ -390,21 +396,15 @@ class DatabaseCache(object):
                 continue
             self.__pifs[p] = {}
             for f in _PIF_ATTRS:
-                if f in [ "tunnel_access_PIF_of", "tunnel_transport_PIF_of" ] and f not in rec:
-                    # XenServer 5.5 network records did not have
-                    # these fields, so allow them to be missing.
-                    pass
-                else:
-                    self.__pifs[p][f] = rec[f]
+                self.__pifs[p][f] = rec[f]
             self.__pifs[p]['other_config'] = {}
             for f in _PIF_OTHERCONFIG_ATTRS:
-                if not rec['other_config'].has_key(f): continue
+                if f not in rec['other_config']: continue
                 self.__pifs[p]['other_config'][f] = rec['other_config'][f]
 
     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] = {}
@@ -423,8 +423,7 @@ class DatabaseCache(object):
 
     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] = {}
@@ -433,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":
@@ -448,7 +446,7 @@ class DatabaseCache(object):
                     self.__networks[n][f] = rec[f]
             self.__networks[n]['other_config'] = {}
             for f in _NETWORK_OTHERCONFIG_ATTRS:
-                if not rec['other_config'].has_key(f): continue
+                if f not in rec['other_config']: continue
                 self.__networks[n]['other_config'][f] = rec['other_config'][f]
 
     def __get_pool_records_from_xapi(self, session):
@@ -462,7 +460,7 @@ class DatabaseCache(object):
                 self.__pools[p][f] = rec[f]
 
             for f in _POOL_OTHERCONFIG_ATTRS:
-                if rec['other_config'].has_key(f):
+                if f in rec['other_config']:
                     self.__pools[p]['other_config'][f] = rec['other_config'][f]
 
     def __to_xml(self, xml, parent, key, ref, rec, attrs):
@@ -473,7 +471,7 @@ class DatabaseCache(object):
             e.setAttribute('ref', ref)
 
         for n,v in rec.items():
-            if attrs.has_key(n):
+            if n in attrs:
                 h,_ = attrs[n]
                 h(xml, e, n, v)
             else:
@@ -504,21 +502,14 @@ class DatabaseCache(object):
             try:
 
                 inventory = self.__read_xensource_inventory()
-                assert(inventory.has_key('INSTALLATION_UUID'))
+                assert('INSTALLATION_UUID' in inventory)
                 log("host uuid is %s" % inventory['INSTALLATION_UUID'])
 
                 host = session.xenapi.host.get_by_uuid(inventory['INSTALLATION_UUID'])
 
                 self.__get_pif_records_from_xapi(session, host)
-
-                try:
-                    self.__get_tunnel_records_from_xapi(session)
-                except XenAPI.Failure, e:
-                    error,details = e.details
-                    if error == "MESSAGE_METHOD_UNKNOWN" and details == "tunnel.get_all":
-                        pass
-
                 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)
@@ -584,13 +575,15 @@ class DatabaseCache(object):
         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,
-                  filter(lambda (ref,rec): uuid == rec['uuid'],
+        pifs = map(lambda ref_rec: ref_rec[0],
+                  filter(lambda ref_rec: uuid == ref_rec[1]['uuid'],
                          self.__pifs.items()))
         if len(pifs) == 0:
             raise Error("Unknown PIF \"%s\"" % uuid)
@@ -600,14 +593,14 @@ class DatabaseCache(object):
         return pifs[0]
 
     def get_pifs_by_device(self, device):
-        return map(lambda (ref,rec): ref,
-                   filter(lambda (ref,rec): rec['device'] == device,
-                          self.__pifs.items()))
+        return list(map(lambda ref_rec: ref_rec[0],
+                   list(filter(lambda ref_rec: ref_rec[1]['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()))
+        return list(map(lambda ref_rec: ref_rec[0],
+                  list(filter(lambda ref_rec: ref_rec[1]['bridge'] == bridge,
+                         self.__networks.items()))))
 
     def get_network_by_bridge(self, bridge):
         #Assumes one network has bridge.
@@ -635,13 +628,13 @@ class DatabaseCache(object):
         return answer
 
     def get_pif_record(self, pif):
-        if self.__pifs.has_key(pif):
+        if pif in self.__pifs:
             return self.__pifs[pif]
         raise Error("Unknown PIF \"%s\"" % pif)
     def get_all_pifs(self):
         return self.__pifs
     def pif_exists(self, pif):
-        return self.__pifs.has_key(pif)
+        return pif in self.__pifs
 
     def get_management_pif(self):
         """ Returns the management pif on host
@@ -653,45 +646,46 @@ class DatabaseCache(object):
         return None
 
     def get_network_record(self, network):
-        if self.__networks.has_key(network):
+        if network in self.__networks:
             return self.__networks[network]
         raise Error("Unknown network \"%s\"" % network)
 
     def get_bond_record(self, bond):
-        if self.__bonds.has_key(bond):
+        if bond in self.__bonds:
             return self.__bonds[bond]
         else:
             return None
 
     def get_vlan_record(self, vlan):
-        if self.__vlans.has_key(vlan):
+        if vlan in self.__vlans:
             return self.__vlans[vlan]
         else:
             return None
 
     def get_pool_record(self):
         if len(self.__pools) > 0:
-            return self.__pools.values()[0]
+            return list(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'):
+    if 'ethtool-speed' in oc:
         val = oc['ethtool-speed']
         if val in ["10", "100", "1000"]:
             settings += ['speed', val]
         else:
             log("Invalid value for ethtool-speed = %s. Must be 10|100|1000." % val)
-    if oc.has_key('ethtool-duplex'):
+    if 'ethtool-duplex' in oc:
         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'):
+    if 'ethtool-autoneg' in oc:
         val = oc['ethtool-autoneg']
         if val in ["true", "on"]:
             settings += ['autoneg', 'on']
@@ -700,8 +694,8 @@ 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"):
-        if oc.has_key("ethtool-" + opt):
+    for opt in ("rx", "tx", "sg", "tso", "ufo", "gso", "gro", "lro"):
+        if "ethtool-" + opt in oc:
             val = oc["ethtool-" + opt]
             if val in ["true", "on"]:
                 offload += [opt, 'on']
@@ -709,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,
@@ -721,12 +717,12 @@ def mtu_setting(nw, type, oc):
     mtu = None
 
     nwrec = db().get_network_record(nw)
-    if nwrec.has_key('MTU'):
+    if 'MTU' in nwrec:
         mtu = nwrec['MTU']
     else:
         mtu = "1500"
         
-    if oc.has_key('mtu'):
+    if 'mtu' in oc:
         log("Override Network.MTU setting on bridge %s from %s.MTU is %s" % \
             (nwrec['bridge'], type, mtu))
         mtu = oc['mtu']
@@ -735,7 +731,7 @@ def mtu_setting(nw, type, oc):
         try:
             int(mtu)      # Check that the value is an integer
             return mtu
-        except ValueError, x:
+        except ValueError as x:
             log("Invalid value for mtu = %s" % mtu)
 
     return None
@@ -762,15 +758,22 @@ def pif_ipdev_name(pif):
 def netdev_exists(netdev):
     return os.path.exists(root_prefix() + "/sys/class/net/" + netdev)
 
+
+def unicode_2to3(string):
+    if sys.version_info < (3,):
+        return string.encode()
+    return string
+
+
 def pif_netdev_name(pif):
     """Get the netdev name for a PIF."""
 
     pifrec = db().get_pif_record(pif)
 
     if pif_is_vlan(pif):
-        return "%(device)s.%(VLAN)s" % pifrec
+        return unicode_2to3("%(device)s.%(VLAN)s" % pifrec)
     else:
-        return pifrec['device']
+        return unicode_2to3(pifrec['device'])
 
 #
 # Bridges
@@ -881,8 +884,7 @@ def pif_get_vlan_masters(pif):
 # Tunnel PIFs
 #
 def pif_is_tunnel(pif):
-    rec = db().get_pif_record(pif)
-    return rec.has_key('tunnel_access_PIF_of') and len(rec['tunnel_access_PIF_of']) > 0
+    return len(db().get_pif_record(pif)['tunnel_access_PIF_of']) > 0
 
 #
 # Datapath base class
@@ -928,7 +930,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.
@@ -957,7 +959,7 @@ def DatapathFactory():
         network_conf = open(root_prefix() + "/etc/xensource/network.conf", 'r')
         network_backend = network_conf.readline().strip()
         network_conf.close()                
-    except Exception, e:
+    except Exception as e:
         raise Error("failed to determine network backend:" + e)
     
     if network_backend == "bridge":