Skip to content

Commit 6b5fa14

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "mypy: Add type annotations to 'nova.pci'"
2 parents 02f4235 + 51d16ad commit 6b5fa14

File tree

9 files changed

+346
-170
lines changed

9 files changed

+346
-170
lines changed

mypy-files.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
nova/compute/manager.py
22
nova/crypto.py
33
nova/network/neutron.py
4+
nova/pci
45
nova/privsep/path.py
56
nova/scheduler/client/report.py
67
nova/scheduler/request_filter.py

nova/pci/devspec.py

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
import abc
1515
import re
1616
import string
17+
import typing as ty
1718

1819
from nova import exception
1920
from nova.i18n import _
21+
from nova import objects
2022
from nova.pci import utils
2123

2224
MAX_VENDOR_ID = 0xFFFF
@@ -29,24 +31,35 @@
2931
REGEX_ANY = '.*'
3032

3133

34+
PCISpecAddressType = ty.Union[ty.Dict[str, str], str]
35+
36+
3237
class PciAddressSpec(metaclass=abc.ABCMeta):
3338
"""Abstract class for all PCI address spec styles
3439
3540
This class checks the address fields of the pci.passthrough_whitelist
3641
"""
3742

43+
def __init__(self, pci_addr: str) -> None:
44+
self.domain = ''
45+
self.bus = ''
46+
self.slot = ''
47+
self.func = ''
48+
3849
@abc.abstractmethod
3950
def match(self, pci_addr):
4051
pass
4152

42-
def is_single_address(self):
53+
def is_single_address(self) -> bool:
4354
return all([
4455
all(c in string.hexdigits for c in self.domain),
4556
all(c in string.hexdigits for c in self.bus),
4657
all(c in string.hexdigits for c in self.slot),
4758
all(c in string.hexdigits for c in self.func)])
4859

49-
def _set_pci_dev_info(self, prop, maxval, hex_value):
60+
def _set_pci_dev_info(
61+
self, prop: str, maxval: int, hex_value: str
62+
) -> None:
5063
a = getattr(self, prop)
5164
if a == ANY:
5265
return
@@ -70,8 +83,10 @@ class PhysicalPciAddress(PciAddressSpec):
7083
This function class will validate the address fields for a single
7184
PCI device.
7285
"""
73-
def __init__(self, pci_addr):
86+
87+
def __init__(self, pci_addr: PCISpecAddressType) -> None:
7488
try:
89+
# TODO(stephenfin): Is this ever actually a string?
7590
if isinstance(pci_addr, dict):
7691
self.domain = pci_addr['domain']
7792
self.bus = pci_addr['bus']
@@ -87,7 +102,7 @@ def __init__(self, pci_addr):
87102
except (KeyError, ValueError):
88103
raise exception.PciDeviceWrongAddressFormat(address=pci_addr)
89104

90-
def match(self, phys_pci_addr):
105+
def match(self, phys_pci_addr: PciAddressSpec) -> bool:
91106
conditions = [
92107
self.domain == phys_pci_addr.domain,
93108
self.bus == phys_pci_addr.bus,
@@ -104,7 +119,7 @@ class PciAddressGlobSpec(PciAddressSpec):
104119
check for wildcards, and insert wildcards where the field is left blank.
105120
"""
106121

107-
def __init__(self, pci_addr):
122+
def __init__(self, pci_addr: str) -> None:
108123
self.domain = ANY
109124
self.bus = ANY
110125
self.slot = ANY
@@ -129,7 +144,7 @@ def __init__(self, pci_addr):
129144
self._set_pci_dev_info('bus', MAX_BUS, '%02x')
130145
self._set_pci_dev_info('slot', MAX_SLOT, '%02x')
131146

132-
def match(self, phys_pci_addr):
147+
def match(self, phys_pci_addr: PciAddressSpec) -> bool:
133148
conditions = [
134149
self.domain in (ANY, phys_pci_addr.domain),
135150
self.bus in (ANY, phys_pci_addr.bus),
@@ -146,7 +161,8 @@ class PciAddressRegexSpec(PciAddressSpec):
146161
The validation includes check for all PCI address attributes and validate
147162
their regex.
148163
"""
149-
def __init__(self, pci_addr):
164+
165+
def __init__(self, pci_addr: dict) -> None:
150166
try:
151167
self.domain = pci_addr.get('domain', REGEX_ANY)
152168
self.bus = pci_addr.get('bus', REGEX_ANY)
@@ -159,7 +175,7 @@ def __init__(self, pci_addr):
159175
except re.error:
160176
raise exception.PciDeviceWrongAddressFormat(address=pci_addr)
161177

162-
def match(self, phys_pci_addr):
178+
def match(self, phys_pci_addr: PciAddressSpec) -> bool:
163179
conditions = [
164180
bool(self.domain_regex.match(phys_pci_addr.domain)),
165181
bool(self.bus_regex.match(phys_pci_addr.bus)),
@@ -187,11 +203,13 @@ class WhitelistPciAddress(object):
187203
| passthrough_whitelist = {"vendor_id":"1137","product_id":"0071"}
188204
189205
"""
190-
def __init__(self, pci_addr, is_physical_function):
206+
def __init__(
207+
self, pci_addr: PCISpecAddressType, is_physical_function: bool
208+
) -> None:
191209
self.is_physical_function = is_physical_function
192210
self._init_address_fields(pci_addr)
193211

194-
def _check_physical_function(self):
212+
def _check_physical_function(self) -> None:
195213
if self.pci_address_spec.is_single_address():
196214
self.is_physical_function = (
197215
utils.is_physical_function(
@@ -200,7 +218,8 @@ def _check_physical_function(self):
200218
self.pci_address_spec.slot,
201219
self.pci_address_spec.func))
202220

203-
def _init_address_fields(self, pci_addr):
221+
def _init_address_fields(self, pci_addr: PCISpecAddressType) -> None:
222+
self.pci_address_spec: PciAddressSpec
204223
if not self.is_physical_function:
205224
if isinstance(pci_addr, str):
206225
self.pci_address_spec = PciAddressGlobSpec(pci_addr)
@@ -212,10 +231,12 @@ def _init_address_fields(self, pci_addr):
212231
else:
213232
self.pci_address_spec = PhysicalPciAddress(pci_addr)
214233

215-
def match(self, pci_addr, pci_phys_addr):
216-
"""Match a device to this PciAddress. Assume this is called given
217-
pci_addr and pci_phys_addr reported by libvirt, no attempt is made to
218-
verify if pci_addr is a VF of pci_phys_addr.
234+
def match(self, pci_addr: str, pci_phys_addr: ty.Optional[str]) -> bool:
235+
"""Match a device to this PciAddress.
236+
237+
Assume this is called with a ``pci_addr`` and ``pci_phys_addr``
238+
reported by libvirt. No attempt is made to verify if ``pci_addr`` is a
239+
VF of ``pci_phys_addr``.
219240
220241
:param pci_addr: PCI address of the device to match.
221242
:param pci_phys_addr: PCI address of the parent of the device to match
@@ -237,51 +258,57 @@ def match(self, pci_addr, pci_phys_addr):
237258

238259

239260
class PciDeviceSpec(PciAddressSpec):
240-
def __init__(self, dev_spec):
261+
def __init__(self, dev_spec: ty.Dict[str, str]) -> None:
241262
self.tags = dev_spec
242263
self._init_dev_details()
243264

244-
def _init_dev_details(self):
265+
def _init_dev_details(self) -> None:
245266
self.vendor_id = self.tags.pop("vendor_id", ANY)
246267
self.product_id = self.tags.pop("product_id", ANY)
268+
self.dev_name = self.tags.pop("devname", None)
269+
self.address: ty.Optional[WhitelistPciAddress] = None
247270
# Note(moshele): The address attribute can be a string or a dict.
248271
# For glob syntax or specific pci it is a string and for regex syntax
249272
# it is a dict. The WhitelistPciAddress class handles both types.
250-
self.address = self.tags.pop("address", None)
251-
self.dev_name = self.tags.pop("devname", None)
273+
address = self.tags.pop("address", None)
252274

253275
self.vendor_id = self.vendor_id.strip()
254276
self._set_pci_dev_info('vendor_id', MAX_VENDOR_ID, '%04x')
255277
self._set_pci_dev_info('product_id', MAX_PRODUCT_ID, '%04x')
256278

257-
if self.address and self.dev_name:
279+
if address and self.dev_name:
258280
raise exception.PciDeviceInvalidDeviceName()
281+
259282
if not self.dev_name:
260-
pci_address = self.address or "*:*:*.*"
261-
self.address = WhitelistPciAddress(pci_address, False)
283+
self.address = WhitelistPciAddress(address or '*:*:*.*', False)
284+
285+
def match(self, dev_dict: ty.Dict[str, str]) -> bool:
286+
address_obj: ty.Optional[WhitelistPciAddress]
262287

263-
def match(self, dev_dict):
264288
if self.dev_name:
265-
address_str, pf = utils.get_function_by_ifname(
266-
self.dev_name)
289+
address_str, pf = utils.get_function_by_ifname(self.dev_name)
267290
if not address_str:
268291
return False
269292
# Note(moshele): In this case we always passing a string
270293
# of the PF pci address
271294
address_obj = WhitelistPciAddress(address_str, pf)
272-
elif self.address:
295+
else: # use self.address
273296
address_obj = self.address
297+
298+
if not address_obj:
299+
return False
300+
274301
return all([
275302
self.vendor_id in (ANY, dev_dict['vendor_id']),
276303
self.product_id in (ANY, dev_dict['product_id']),
277304
address_obj.match(dev_dict['address'],
278305
dev_dict.get('parent_addr'))])
279306

280-
def match_pci_obj(self, pci_obj):
307+
def match_pci_obj(self, pci_obj: 'objects.PciDevice') -> bool:
281308
return self.match({'vendor_id': pci_obj.vendor_id,
282309
'product_id': pci_obj.product_id,
283310
'address': pci_obj.address,
284311
'parent_addr': pci_obj.parent_addr})
285312

286-
def get_tags(self):
313+
def get_tags(self) -> ty.Dict[str, str]:
287314
return self.tags

0 commit comments

Comments
 (0)