Ido Barkan has uploaded a new change for review.

Change subject: network: restore sriov devices number of vfs
......................................................................

network: restore sriov devices number of vfs

vdsm-restore-net-config will attempt to restore the number of vfs
from the last successful change. If no sriov devices are found the
function only tries to collect garbage. This is done before network
restoration so that networks can be configured based on the
restored vfs.

The patch also introduces a 'safe' changing of number of vfs of an
sriov card which also checks if the connectivity to the engine was
lost as a consequence.

Change-Id: I76b898019840ffe65939ffad4a1e98829ad3c887
Signed-off-by: Ido Barkan <ibar...@redhat.com>
---
M vdsm/network/api.py
M vdsm/vdsm-restore-net-config
2 files changed, 85 insertions(+), 5 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/88/40088/1

diff --git a/vdsm/network/api.py b/vdsm/network/api.py
index bc2dbd2..07f2640 100755
--- a/vdsm/network/api.py
+++ b/vdsm/network/api.py
@@ -40,6 +40,7 @@
 import hooks  # TODO: Turn into parent package import when vdsm is a package
 
 CONNECTIVITY_TIMEOUT_DEFAULT = 4
+_SYSFS_SRIOV_NUMVFS = '/sys/bus/pci/devices/{}/sriov_numvfs'
 
 
 def _getConfiguratorClass():
@@ -541,17 +542,51 @@
                                          'connectivity check failed')
 
 
-def changeNumvfs(device_name, numvfs):
-    with open('/sys/bus/pci/devices/{}/sriov_numvfs'.format(
-            device_name), 'w', 0) as f:
+def _update_num_vfs(device_name, num_vfs):
+    with open(_SYSFS_SRIOV_NUMVFS.format(device_name), 'w', 0) as f:
         # Zero needs to be written first in order to remove previous VFs.
         # Trying to just write the number (if n > 0 VF's existed before)
         # results in 'write error: Device or resource busy'
         # https://www.kernel.org/doc/Documentation/PCI/pci-iov-howto.txt
         f.write('0')
+        f.write(str(num_vfs))
+
+
+def _persist_num_vfs(device_name, numvfs):
+    dir_path = os.path.join(constants.P_VDSM_LIB, 'virtual_functions')
+    try:
+        os.makedirs(dir_path)
+    except OSError as ose:
+        if errno.EEXIST != ose.errno:
+            raise
+    with open(dir_path, device_name, 'w') as f:
         f.write(str(numvfs))
 
 
+def changeNumvfs(device_name, num_vfs):
+    """Change number of virtual functions of a device in a 'safe' way. If the
+    connectivity to engine is lost as a consequence, the value is restored.
+    Since calling this verb is currently blocked by engine if this device is
+    already in use, the logic does not attempt to do anything further, such as
+    restoring possibly lost networks.
+    The persistence is stored in a place which is writable also in ovirt-node.
+    Garbage is will be collected during restoration.
+    """
+    original_value = _get_num_vfs(device_name)
+    _update_num_vfs(device_name, num_vfs)
+    if not clientSeen():
+        _update_num_vfs(device_name, original_value)
+        raise ConfigNetworkError(
+            ne.ERR_LOST_CONNECTION, 'connectivity check failed')
+
+    _persist_num_vfs(device_name, num_vfs)
+
+
+def _get_num_vfs(device_name):
+    with open(_SYSFS_SRIOV_NUMVFS.format(device_name), 'r', 0) as f:
+        return int(f.read())
+
+
 def _validateNetworkSetup(networks, bondings):
     for network, networkAttrs in networks.iteritems():
         if networkAttrs.get('remove', False):
diff --git a/vdsm/vdsm-restore-net-config b/vdsm/vdsm-restore-net-config
index 21d6592..afe4abd 100755
--- a/vdsm/vdsm-restore-net-config
+++ b/vdsm/vdsm-restore-net-config
@@ -27,21 +27,64 @@
 
 from vdsm.config import config
 from vdsm import netinfo
-from vdsm.constants import P_VDSM_RUN
+from vdsm.constants import P_VDSM_RUN, P_VDSM_LIB
+import hostdev
 
 # Ifcfg persistence restoration
 from network.configurators import ifcfg
 
 # Unified persistence restoration
-from network.api import setupNetworks
+from network.api import setupNetworks, changeNumvfs
 from network import configurators
 from vdsm.netconfpersistence import RunningConfig, PersistentConfig
 import pkgutil
 
 _NETS_RESTORED_MARK = os.path.join(P_VDSM_RUN, 'nets_restored')
+_VIRTUAL_FUNCTIONS_PATH = os.path.join(P_VDSM_LIB, 'virtual_functions')
+
+
+def _get_sriov_devices():
+    devices = hostdev.list_by_caps()
+    sriov_pci_addrs = [addr for addr, device in devices.iteritems()
+                       if 'totalvfs' in device['params']]
+    net_devs = [device for device in devices.itervalues()
+                if device['params']['capability'] == 'net']
+    return [device['params']['interface'] for device in net_devs
+            if device['params']['parent'] in sriov_pci_addrs]
+
+
+def _get_persisted_numvfs(existing_sriov_devices):
+    num_vfs_by_device = {}
+    missing_devices = []
+    for file_name in os.listdir(_VIRTUAL_FUNCTIONS_PATH):
+        if file_name not in existing_sriov_devices:
+            missing_devices.append(file_name)
+        else:
+            with open(os.path.join(
+                    _VIRTUAL_FUNCTIONS_PATH, file_name), 'r') as f:
+                num_vfs_by_device[file_name] = int(f.read().strip())
+
+    return num_vfs_by_device, missing_devices
+
+
+def _remove_missing_devices_persistence(missing_devices):
+    for file_name in missing_devices:
+        os.remove(os.path.join(_VIRTUAL_FUNCTIONS_PATH, file_name))
+
+
+def _restore_sriov_num_vfs():
+    sriov_devices = _get_sriov_devices()
+    persisted_num_vfs, missing_devices = _get_persisted_numvfs(sriov_devices)
+
+    for device in sriov_devices:
+        changeNumvfs(device, persisted_num_vfs[device])
+
+    _remove_missing_devices_persistence(missing_devices)
 
 
 def ifcfg_restoration():
+    _restore_sriov_num_vfs()
+
     configWriter = ifcfg.ConfigWriter()
     configWriter.restorePersistentBackup()
 
@@ -51,6 +94,8 @@
     Builds a setupNetworks command from the persistent configuration to set it
     as running configuration.
     """
+    _restore_sriov_num_vfs()
+
     runningConfig = RunningConfig()
     removeNetworks = {}
     removeBonds = {}


-- 
To view, visit https://gerrit.ovirt.org/40088
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I76b898019840ffe65939ffad4a1e98829ad3c887
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Ido Barkan <ibar...@redhat.com>
_______________________________________________
vdsm-patches mailing list
vdsm-patches@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches

Reply via email to