93 lines
3.1 KiB
Python
93 lines
3.1 KiB
Python
#
|
|
# Copyright (c) 2019 StarlingX.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
|
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# All Rights Reserved.
|
|
#
|
|
|
|
""" Define pci_irq_affinity_provider class"""
|
|
|
|
import utils as pci_utils
|
|
from driver import AffinePciIrqDriver
|
|
from nova_provider import novaClient
|
|
from log import LOG
|
|
|
|
|
|
class pci_irq_affinity_provider:
|
|
def __init__(self):
|
|
self.affinePciIrqDriver = AffinePciIrqDriver()
|
|
self.inst_dict = {}
|
|
|
|
def reset_irq_affinity(self, uuid, irqs=None, msi_irqs=None):
|
|
"""Reset irq affinity for instance
|
|
|
|
The instance has already been deleted or
|
|
related PCI not used by it anymore.
|
|
"""
|
|
if irqs or msi_irqs:
|
|
# reset irq affinity for specified irqs
|
|
_irqs = irqs
|
|
_msi_irqs = msi_irqs
|
|
|
|
elif uuid in self.inst_dict:
|
|
# reset all irq affinity for deleted instance
|
|
_irqs = self.inst_dict[uuid][0]
|
|
_msi_irqs = self.inst_dict[uuid][1]
|
|
else:
|
|
LOG.debug("No pci affinity need to be reset for instance=%s!" % uuid)
|
|
return
|
|
|
|
try:
|
|
with open('/proc/irq/default_smp_affinity') as f:
|
|
cpulist = f.readline().strip()
|
|
LOG.debug("default smp affinity bitmap:%s" % cpulist)
|
|
|
|
for x in [_irqs, _msi_irqs]:
|
|
if len(x) > 0:
|
|
pci_utils.set_irq_affinity(True, x, cpulist)
|
|
|
|
except Exception as e:
|
|
LOG.error("Failed to reset smp affinity! error=%s" % e)
|
|
|
|
LOG.info("Reset smp affinity done for instance=%s!" % uuid)
|
|
|
|
def instance_irq_pcpulist_update(self, uuid, irqs, msi_irqs, cpulist):
|
|
if uuid in self.inst_dict:
|
|
_prev = self.inst_dict[uuid]
|
|
# get irqs that not appear anymore.
|
|
_irqs = _prev[0].difference(irqs)
|
|
_msi_irqs = _prev[1].difference(msi_irqs)
|
|
|
|
# reset pci affinity for those pcis not used by intance anymore
|
|
if (len(_irqs) + len(_msi_irqs)) > 0:
|
|
self.reset_irq_affinity(uuid, _irqs, _msi_irqs)
|
|
|
|
self.inst_dict[uuid] = [irqs, msi_irqs, cpulist]
|
|
LOG.debug(self.inst_dict)
|
|
|
|
def affine_pci_dev_instance(self, instance, wait_for_irqs=True):
|
|
if instance is not None:
|
|
if instance.get_cpu_policy() == 'dedicated' and instance.get_pci_devices():
|
|
LOG.debug("Instance=%s use dedicated cpu policy!!!" % instance.uuid)
|
|
irqs, msi_irqs, cpulist = \
|
|
self.affinePciIrqDriver.affine_pci_dev_irqs(instance, wait_for_irqs)
|
|
# record instance on which pci affinity has been applied
|
|
self.instance_irq_pcpulist_update(instance.uuid, irqs, msi_irqs, cpulist)
|
|
return
|
|
|
|
def audit_pci_irq_affinity(self):
|
|
# audit instance PCI devices periodically
|
|
filters = {'vm_state': 'active',
|
|
'task_state': None,
|
|
'deleted': False}
|
|
instances = novaClient.get_instances(filters)
|
|
for inst in instances:
|
|
self.affine_pci_dev_instance(inst, wait_for_irqs=False)
|
|
|
|
|
|
pciIrqAffinity = pci_irq_affinity_provider()
|